vedo icon indicating copy to clipboard operation
vedo copied to clipboard

Adding a logo-widget

Open RubendeBruin opened this issue 2 years ago • 6 comments

Is there an easy way in vedo to add a logo-widget? Something in line with addIcon, but then creating a static image instead of one that rotates?

logo_rep = vtk.vtkLogoRepresentation()
logo_rep.SetImage(self._colorbar.GetInput())
logo_rep.SetPosition([0.1, 0.5])
logo_rep.SetImageProperty(logo_rep.GetImageProperty())

logowidget = vtk.vtkLogoWidget()
logowidget.SetInteractor(self.screen.interactor)
logowidget.SetRepresentation(logo_rep)
logowidget.On()
logowidget.Render()

plotter.widgets.append(logowidget)

if not, would a PR with addLogo be welcome?

RubendeBruin avatar Oct 01 '21 17:10 RubendeBruin

Sure, sounds a nice idea! I couldn't find how to control size though:

import vtk
from vedo import *

s = Sphere()
logpic = Picture("https://user-images.githubusercontent.com/32848391/110343974-530a4e00-802d-11eb-88c0-129753028ff9.png")
# logpic = Picture("https://upload.wikimedia.org/wikipedia/commons/thumb/7/76/Visualization_Toolkit_logo.svg/1200px-Visualization_Toolkit_logo.svg.png")

plotter = Plotter()

logo_rep = vtk.vtkLogoRepresentation()
logo_rep.SetImage(logpic._data)
logo_rep.SetPosition([0.85, 0.05])
logo_rep.GetImageProperty().SetOpacity(1)

logowidget = vtk.vtkLogoWidget()
logowidget.SetInteractor(plotter.interactor)
logowidget.SetRepresentation(logo_rep)
logowidget.On()

plotter.widgets.append(logowidget)

plotter.show(s, axes=1)

we have something similar in examples: other/icon.py and other/inset.py, but the images solidly move with the world coordinates.

marcomusy avatar Oct 02 '21 11:10 marcomusy

I also can not disable user control of the widget. According to the docs SelectableOff() and ResizableOff() should stop user interaction, but I'm still able to move and resize it.

Alternatively an Actor2D with vtkImageMapper can be used, but also here I do not get how to resize the image. Also positioning is in screen coordinates (pixels) rather than view coordinates. Even though the documentation states that is view coordinates...

import vtk
from vedo import *

s = Sphere()
logpic = Picture("https://user-images.githubusercontent.com/32848391/110343974-530a4e00-802d-11eb-88c0-129753028ff9.png")
# logpic = Picture("https://upload.wikimedia.org/wikipedia/commons/thumb/7/76/Visualization_Toolkit_logo.svg/1200px-Visualization_Toolkit_logo.svg.png")

plotter = Plotter()

imagemapper = vtk.vtkImageMapper()
imagemapper.SetInputData(logpic._data)
imagemapper.SetColorWindow(255)
imagemapper.SetColorLevel(127.5)


image = vtk.vtkActor2D()
image.SetMapper(imagemapper)
image.SetWidth(20)  # does not seem to do anything
image.SetHeight(0.01)  # does not seem to do anything
# image.SetDisplayPosition(200,200)  # position in screen coordinates, not view coordinates
image.SetPosition(100,100)  # same same

plotter.add(image)

plotter.show(s, axes=1)

will ask on the vtk forum before continuing.

(In my case I wanted to have my image in a fixed size on the bottom left, which fortunately is a case that works :-) )

RubendeBruin avatar Oct 02 '21 14:10 RubendeBruin

Oh I think I found it....:


import vtk
from vedo import *

pos = (0.05,0.05)
scale = 0.2

logpic = Picture("https://user-images.githubusercontent.com/32848391/110343974-530a4e00-802d-11eb-88c0-129753028ff9.png")

plotter = Plotter()

imagemapper = vtk.vtkImageMapper()
imagemapper.SetInputData(logpic._data)
imagemapper.SetColorWindow(255)
imagemapper.SetColorLevel(127.5)
imagemapper.RenderToRectangleOn()

image = vtk.vtkActor2D()
image.SetMapper(imagemapper)

image.GetPositionCoordinate().SetCoordinateSystem(1)
# 0. Displays
# 1. Normalized Display
# 2. Viewport (origin is the bottom-left corner of the window)
# 3. Normalized Viewport
# 4. View (origin is the center of the window)
# 5. World (anchor the 2d image to mesh)

image.SetWidth( scale)
image.SetHeight(scale*logpic.shape[1]/logpic.shape[0])
image.SetPosition(pos)

plotter.show(Sphere(), image, axes=1)

it was RenderToRectangleOn

marcomusy avatar Oct 02 '21 16:10 marcomusy

uhm.. still doesnt work very well if I put eg. pos = (0.75,0.05), it looks streched

PS: I was thinking maybe it would be cool to have it like a method of Picture:


import vtk
from vedo import *

def make2d(pos=(0.05,0.05), selfpic=None, coordsys=1, scale=0.1): # to become:
#def make2d(self, pos=(0.05,0.05), coordsys=1, scale=0.1):

    imagemapper = vtk.vtkImageMapper()
    imagemapper.SetInputData(selfpic._data)
    imagemapper.SetColorWindow(selfpic.window())
    imagemapper.SetColorLevel(selfpic.level())
    imagemapper.RenderToRectangleOn()

    image = vtk.vtkActor2D()
    image.SetMapper(imagemapper)

    image.GetPositionCoordinate().SetCoordinateSystem(coordsys)

    image.SetWidth(scale)
    image.SetHeight(scale*selfpic.shape[1]/selfpic.shape[0])
    image.SetPosition(pos)
    return image

plotter = Plotter()

logo = Picture("https://user-images.githubusercontent.com/32848391/110343974-530a4e00-802d-11eb-88c0-129753028ff9.png")

logo2d = make2d(selfpic=logo) # to become:
# logo2d = logo.make2d()

plotter.show(Sphere(), logo2d, axes=1)

what do you think?

marcomusy avatar Oct 02 '21 19:10 marcomusy

I got the idea that setting position (lower-left) and position2 (the upper-right corner) using vtkCoordinates should do the trick. I got it working for position, but as soon as I try to do anything with position2 I get unexpected results....

The following creates a reference coordinate in the upper-right corner and then places the image to the lower-left of that by setting position. If I disable the RenderToRectangleOn() then I get a nice picture in the upper-right corner. But I loose the possibility to resize it. For me that would be not ideal but acceptable. I can always resize a picture with PIL or something before putting it in.

Your suggestion to do:

logo = Picture(input) actor = logo.make2d() plotter.add(actor)

is good I think. The idea that I had in mind was to use the same mechanism as for the widgets plt.addCornerImage or something but your proposal is more flexible.

import vtk
from vedo import *


logpic = Picture("https://user-images.githubusercontent.com/32848391/110343974-530a4e00-802d-11eb-88c0-129753028ff9.png")

imagemapper = vtk.vtkImageMapper()
imagemapper.SetInputData(logpic._data)
imagemapper.SetColorWindow(255)
imagemapper.SetColorLevel(127.5)
# imagemapper.RenderToRectangleOn()  # no longer able to set the scale, but at least the image does not deform anymore
# aspect = logpic.shape[1]/logpic.shape[0] # (width / height)

image = vtk.vtkActor2D()
image.SetMapper(imagemapper)

# https://vtk.org/doc/nightly/html/classvtkCoordinate.html

position1_coordinate = image.GetPositionCoordinate()

# position1 : The position variable controls the lower left corner of the Actor2D
# position2 is the position of the upper-right corner of the actor. It is by default relative to Position and in normalized viewport coordinates.

refpos = vtk.vtkCoordinate()
refpos.SetCoordinateSystemToNormalizedViewport()
refpos.SetValue(1,1)  # upper right corner
#
# # Define the lower-left corner relative to the ref-position and in pixels
position1_coordinate.SetReferenceCoordinate(refpos)
position1_coordinate.SetCoordinateSystemToViewport() #  x-y pixel values in viewport
position1_coordinate.SetValue(-logpic.shape[0],-logpic.shape[1])

# # Now try to do the same with position2
#
# Position2 is supposed to set the upper-right corner of the actor
# but it doens't work for me
#
# position2_coordinate = image.GetPosition2Coordinate()
# position2_coordinate.SetReferenceCoordinate(refpos)
# position2_coordinate.SetCoordinateSystemToViewport() # x-y pixel values in viewport
# position2_coordinate.SetValue(0,0)

plotter = Plotter()
plotter.show(Sphere(), image, axes=1)

crosslink: https://discourse.vtk.org/t/positioning-and-scaling-of-actor2d-with-image/6754

RubendeBruin avatar Oct 02 '21 20:10 RubendeBruin

yes... very confusing! :( moreover the actor2d aspect ratio is not maintained when resizing the window manually

marcomusy avatar Oct 02 '21 21:10 marcomusy