I have started to work with Python's trimesh
package and the first thing I want to do is to set the size of the graphics window and its position on the screen.
I figured out how to resize the graphics window, as the simple code below (from https://github.com/mikedh/trimesh/blob/main/examples/colors.ipynb) shows:
import trimesh
# The XAML file is found at https://github.com/mikedh/trimesh/blob/main/models/machinist.XAML
mesh = trimesh.load("machinist.XAML", process=False)
mesh.visual.kind
# Resolution is an undocumated argument - I had to figure it out myself
mesh.show(resolution=(600,600))
But I also want to center the mesh window on screen. Does anyone know how?
After looking through the classes and methods for a quite a while, I finally found a solution.
The show
method in the Scene
class accepts a SceneViewer
class as its viewer
parameter (which is the default viewer, unless in a notebook)
The SceneViewer
itself inherits from the pyglet.window.Window
, which does have a set_location
method. So, I ended up creating a custom class CenteredSceneViewer
that centers itself by calculating the x
and y
coordinates of the centered window and invoking the set_location
:
import trimesh
from trimesh.viewer.windowed import SceneViewer
from pyglet.canvas import Display
# A SceneViewer that will center itself on the screen
class CenteredSceneViewer(SceneViewer):
def __init__(self, *args, **kwargs):
# Get the screen resolution
self.resolution = kwargs.get("resolution", (600, 600))
display = Display()
screen = display.get_default_screen()
self.screen_width = screen.width
self.screen_height = screen.height
# We only need to center once
self.centered = False
super(CenteredSceneViewer, self).__init__(*args, **kwargs)
def dispatch_event(self, *args):
if not self.centered:
# Calculate the position to center the window
window_x = (self.screen_width - self.resolution[0]) // 2
window_y = (self.screen_height - self.resolution[1]) // 2
# Set the location of the window
self.set_location(window_x, window_y)
self.centered = True
super(CenteredSceneViewer, self).dispatch_event(*args)
mesh = trimesh.load("machinist.XAML", process=False)
mesh.show(viewer=CenteredSceneViewer, resolution=(600, 600))