Beispiel #1
0
class Canvas(app.Canvas):
    def __init__(self):
        app.Canvas.__init__(self, 'Cube', keys='interactive',
                            size=(400, 400))

        self.cube = CubeVisual((1.0, 0.5, 0.25), color='red',
                               edge_color='black')
        self.quaternion = Quaternion()

        # Create a TransformSystem that will tell the visual how to draw
        self.cube_transform = transforms.AffineTransform()
        self.cube_transform.scale((100, 100, 0.001))
        self.cube_transform.translate((200, 200))
        self.tr_sys = transforms.TransformSystem(self)
        self.tr_sys.visual_to_document = self.cube_transform
        self.show()

    def on_draw(self, event):
        gloo.set_viewport(0, 0, *self.physical_size)
        gloo.clear('white')
        self.tr_sys.auto_configure()
        self.cube.draw(self.tr_sys)

    def on_mouse_move(self, event):
        if event.button == 1 and event.last_event is not None:
            x0, y0 = event.last_event.pos
            x1, y1 = event.pos
            w, h = self.size
            self.quaternion = (self.quaternion *
                               Quaternion(*_arcball(x0, y0, w, h)) *
                               Quaternion(*_arcball(x1, y1, w, h)))
            self.cube_transform.matrix = self.quaternion.get_matrix()
            self.cube_transform.scale((100, 100, 0.001))
            self.cube_transform.translate((200, 200))
            self.update()
Beispiel #2
0
class Canvas(app.Canvas):
    def __init__(self):
        app.Canvas.__init__(self, 'Cube', keys='interactive', size=(400, 400))

        self.cube = BoxVisual(1.0, 0.5, 0.25, color='red', edge_color='black')
        self.cube.transform = transforms.MatrixTransform()
        self.cube.transform.scale((100, 100, 0.001))
        self.cube.transform.translate((200, 200))

        self.quaternion = Quaternion()
        self.show()

    def on_resize(self, event):
        vp = (0, 0, self.physical_size[0], self.physical_size[1])
        self.context.set_viewport(*vp)
        self.cube.transforms.configure(canvas=self, viewport=vp)

    def on_draw(self, event):
        self.context.clear('white')
        self.cube.draw()

    def on_mouse_move(self, event):
        if event.button == 1 and event.last_event is not None:
            x0, y0 = event.last_event.pos
            x1, y1 = event.pos
            w, h = self.size
            self.quaternion = (self.quaternion *
                               Quaternion(*_arcball(x0, y0, w, h)) *
                               Quaternion(*_arcball(x1, y1, w, h)))
            self.cube.transform.matrix = self.quaternion.get_matrix()
            self.cube.transform.scale((100, 100, 0.001))
            self.cube.transform.translate((200, 200))
            self.update()
Beispiel #3
0
class Canvas(app.Canvas):
    def __init__(self):
        app.Canvas.__init__(self, 'Cube', keys='interactive',
                            size=(400, 400))

        self.cube = CubeVisual((1.0, 0.5, 0.25), color='red',
                               edge_color='black')
        self.cube.transform = transforms.MatrixTransform()
        self.cube.transform.scale((100, 100, 0.001))
        self.cube.transform.translate((200, 200))

        self.quaternion = Quaternion()
        self.show()

    def on_resize(self, event):
        vp = (0, 0, self.physical_size[0], self.physical_size[1])
        self.context.set_viewport(*vp)
        self.cube.transforms.configure(canvas=self, viewport=vp)

    def on_draw(self, event):
        self.context.clear('white')
        self.cube.draw()

    def on_mouse_move(self, event):
        if event.button == 1 and event.last_event is not None:
            x0, y0 = event.last_event.pos
            x1, y1 = event.pos
            w, h = self.size
            self.quaternion = (self.quaternion *
                               Quaternion(*_arcball(x0, y0, w, h)) *
                               Quaternion(*_arcball(x1, y1, w, h)))
            self.cube.transform.matrix = self.quaternion.get_matrix()
            self.cube.transform.scale((100, 100, 0.001))
            self.cube.transform.translate((200, 200))
            self.update()
Beispiel #4
0
class Canvas(app.Canvas):
    def __init__(self):
        app.Canvas.__init__(self, 'Cube', keys='interactive',
                            size=(400, 400))

        self.cube = CubeVisual((1.0, 0.5, 0.25), color='red',
                               edge_color='black')
        self.quaternion = Quaternion()

        # Create a TransformSystem that will tell the visual how to draw
        self.cube_transform = transforms.AffineTransform()
        self.cube_transform.scale((100, 100, 0.001))
        self.cube_transform.translate((200, 200))
        self.tr_sys = transforms.TransformSystem(self)
        self.tr_sys.visual_to_document = self.cube_transform
        self.show()

    def on_draw(self, event):
        gloo.set_viewport(0, 0, *self.physical_size)
        gloo.clear('white')
        self.tr_sys.auto_configure()
        self.cube.draw(self.tr_sys)

    def on_mouse_move(self, event):
        if event.button == 1 and event.last_event is not None:
            x0, y0 = event.last_event.pos
            x1, y1 = event.pos
            w, h = self.size
            self.quaternion = (self.quaternion *
                               Quaternion(*_arcball(x0, y0, w, h)) *
                               Quaternion(*_arcball(x1, y1, w, h)))
            self.cube_transform.matrix = self.quaternion.get_matrix()
            self.cube_transform.scale((100, 100, 0.001))
            self.cube_transform.translate((200, 200))
            self.update()
    def transformCube(self, t, q):
        quaternion = Quaternion(*q)
        self._transform.reset()
        self._transform.matrix = quaternion.get_matrix()
        self._transform.translate(t)

        x, y, z = t
        self._xPos = np.append(self._xPos, x)
        self._yPos = np.append(self._yPos, y)
        self._zPos = np.append(self._zPos, z)
        self._plot.set_data((self._xPos.transpose(), self._yPos.transpose(),
                             self._zPos.transpose()),
                            symbol=None)
Beispiel #6
0
class RGBDMultiView(app.Canvas):
    """ """
    def __init__(self, sensor_type="OrbbecAstra", sensor_scale=1.0):
        app.Canvas.__init__(self, keys='interactive', size=(1280, 1024))
        self.title = 'RGBDMultiView'
        self.quaternion = Quaternion()  # for mouse movement

        self.cam_params = GetCameraParameters(sensor_type, sensor_scale)

        self.fov = 30
        ps = self.pixel_scale
        self.playbackSpeed = 1

        # view and model control variables
        self.tshift = 0.05  # the amount to translate by
        self.rshift = 0.05  # amount to increase rotation by
        self.scaleFactor = 1000  # the amount to scale the input model by
        self.default_camera_view()

        self.view = np.dot(self.rotMat, self.transMat)
        self.model = np.eye(4, dtype=np.float32)
        self.projection = np.eye(4, dtype=np.float32)

        self.GL_progs = {}  # name : data for a single frame

        self.apply_zoom()

        gloo.set_state('translucent', clear_color='gray')

        self.timer = app.Timer('auto', connect=self.on_timer, start=False)

    def on_timer(self, event):
        if self.nframe_curr < self.nframe_total - self.playbackSpeed:  # if we still got images, keep loading them
            self.nframe_curr += self.playbackSpeed
            self.set_frame(self.nframe_curr)
        else:
            # no more images means we're at the end so we should stop the timer allowing the video to
            # be reverse or restarted by through the spacebar
            if self.timer.running: self.timer.stop()

        self.update()

    def on_mouse_move(self, event):
        if event.button == 1 and event.last_event is not None:
            x0, y0 = event.last_event.pos
            x1, y1 = event.pos
            w, h = self.size
            self.quaternion = (self.quaternion *
                               Quaternion(*_arcball(x0, y0, w, h)) *
                               Quaternion(*_arcball(x1, y1, w, h)))

            self.rotMat = self.quaternion.get_matrix()
            self.view = np.dot(self.rotMat, self.transMat)
            for k, prog in self.GL_progs.items():
                prog['u_view'] = self.view
                prog['u_model'] = self.model
            self.update()

    def default_camera_view(self):
        """ Set the view matrics to their default values """
        self.offX = 0.0  # actual amounts translated thus far
        self.offY = -0.6
        self.zoomAmount = 2.5
        self.centerCoord = (0, 0, 0)  # center of the current point cloud frame
        self.rotX = 9.3
        self.rotY = 6.3
        self.rotZ = 0.0
        self.transMat = translate((self.offX, self.offY, -self.zoomAmount))
        self.rotMat = rotationMatrix((self.rotX, self.rotY, self.rotZ))

        q = quaternion_from_matrix(self.rotMat)  ## just for mouse arc ball
        self.quaternion.w = q[0]
        self.quaternion.x = q[1]
        self.quaternion.y = q[2]
        self.quaternion.z = q[3]

    def print_camera_view(self):
        print(self.offX, self.offY, self.zoomAmount)
        print(self.rotX, self.rotY, self.rotZ)
        print()

    def on_key_press(self, event):
        ### pause and play
        if event.text == ' ':
            if self.timer.running: self.timer.stop()
            else: self.timer.start()

        ### manually advance through the frames
        elif event.text == ',' and self.nframe_curr >= self.playbackSpeed:
            self.nframe_curr -= self.playbackSpeed
            self.set_frame(self.nframe_curr)
            self.update()
        elif event.text == '.':
            if self.nframe_curr < self.nframe_total - self.playbackSpeed:
                self.nframe_curr += self.playbackSpeed
            elif self.nframe_curr < self.nframe_total - 1:
                self.nframe_curr += 1

            self.set_frame(self.nframe_curr)
            self.update()

        ### camera manipulation
        if event.text in ['w', 'a', 's', 'd']:  # planar translations
            if event.text == 'w': self.offY += self.tshift
            elif event.text == 'a': self.offX -= self.tshift
            elif event.text == 's': self.offY -= self.tshift
            elif event.text == 'd': self.offX += self.tshift
            self.transMat = translate((self.offX, self.offY, -self.zoomAmount))

        if event.text in ['q', 'e', 'z', 'c', 'r',
                          'v']:  # rotation about the axis
            if event.text == 'q': self.rotX += self.rshift
            elif event.text == 'e': self.rotX -= self.rshift
            elif event.text == 'z': self.rotY += self.rshift
            elif event.text == 'c': self.rotY -= self.rshift
            elif event.text == 'r': self.rotZ += self.rshift
            elif event.text == 'v': self.rotZ -= self.rshift
            self.rotMat = rotationMatrix((self.rotX, self.rotY, self.rotZ))

        ### reset camera to original default orientation
        if event.text == 'x':
            self.print_camera_view()
            self.default_camera_view()

        if event.text == 'p':
            strTopFolder = "F:/data/deep-learning/additive_depth/98_vr_calib/"
            strFolderName = "test01_img_seq"
            strMultiviewFolder = os.path.join(strTopFolder, strFolderName)
            strPosesFile = os.path.join(strMultiviewFolder, "poses.txt")
            self.sensor_props = ReadManualCalibPoses(strPosesFile)
            for s in sensor_props:
                s.load_image_files(strMultiviewFolder)

        self.view = np.dot(self.rotMat, self.transMat)
        for k, prog in self.GL_progs.items():
            prog['u_view'] = self.view
            prog['u_model'] = self.model

        self.update()

    def on_resize(self, event):
        self.apply_zoom()

    def on_mouse_wheel(self, event):
        self.zoomAmount -= event.delta[1] / 2.0
        self.transMat = translate((self.offX, self.offY, -self.zoomAmount))
        self.view = np.dot(self.rotMat, self.transMat)
        for k, prog in self.GL_progs.items():
            prog['u_view'] = self.view
        self.update()

    def on_draw(self, event):
        gloo.clear()
        for k, prog in self.GL_progs.items():
            prog.draw('points')

    def apply_zoom(self):
        gloo.set_viewport(0, 0, self.physical_size[0], self.physical_size[1])
        self.projection = perspective(self.fov,
                                      self.size[0] / float(self.size[1]), 0.01,
                                      10000.0)
        for k, prog in self.GL_progs.items():
            prog['u_projection'] = self.projection

    def load_frame_data(self, frame_n):
        '''
        load_frame_data

        Arguments:
            frame_n: int obtain the frame number for the stream

        Return:
            frame_data: array contain three camera and contain [numVertice , xyz , rgb]
        '''
        frame_data = {}
        for s in self.sensor_props:
            depthImg = cv2.imread(s.imgs_depth[frame_n],
                                  -1)  ## load frames and compute point cloud
            clrImg = cv2.imread(s.imgs_color[frame_n], -1)
            ptcloud, nVertices = image_fusion(self.cam_params, depthImg,
                                              clrImg)

            transformedPtcloud = transform_pointcloud_vectorized(
                ptcloud, s.rotationMatrix(), s.translationMatrix())
            xyz, rgb = np.hsplit(transformedPtcloud, 2)

            ## TODO: extra post-processing to convert points close to the camera to a specific color

            frame_data[s.name] = [nVertices, xyz, rgb]

        return frame_data

    def load_frame_to_stl(self, frame_n):
        '''
        load_frame_data

        Arguments:
            frame_n: int obtain the frame number for the stream

        Return:
            frame_data: array contain three camera and contain [numVertice , xyz , rgb]
        '''
        data = np.zeros(6, dtype=mesh.Mesh.dtype)

        frame_data = {}

        xyzpcd, rgbpcd = [], []

        for i, s in enumerate(self.sensor_props):
            depthImg = cv2.imread(s.imgs_depth[frame_n],
                                  -1)  ## load frames and compute point cloud
            clrImg = cv2.imread(s.imgs_color[frame_n], -1)
            ptcloud, nVertices = image_fusion(self.cam_params, depthImg,
                                              clrImg)

            transformedPtcloud = transform_pointcloud_vectorized(
                ptcloud, s.rotationMatrix(), s.translationMatrix())
            xyz, rgb = np.hsplit(transformedPtcloud, 2)

            xyzpcd.insert(i, xyz)
            rgbpcd.insert(i, rgb)
            ## TODO: extra post-processing to convert points close to the camera to a specific color

            frame_data[s.name] = [nVertices, xyz, rgb]

        rgbpcd = np.vstack((rgbpcd[0], rgbpcd[1], rgbpcd[2]))
        xyzpcd = np.vstack((xyzpcd[0], xyzpcd[1], xyzpcd[2]))

        print(rgbpcd.shape, xyzpcd.shape)

        return xyzpcd, rgbpcd, frame_data

    def set_frame(self, frame_number):
        self.nframe_curr = frame_number
        frame_data = self.load_frame_data(self.nframe_curr)

        for k, prog in self.GL_progs.items():
            nVertices, xyz, rgb = frame_data[k]

            ## load and bind the current frame data to the GL program
            data = np.zeros(nVertices, [('a_position', np.float32, 3),
                                        ('a_bg_color', np.float32, 4),
                                        ('a_fg_color', np.float32, 4),
                                        ('a_size', np.float32, 1)])
            data['a_position'] = np.array(xyz / self.scaleFactor)
            data['a_bg_color'] = np.c_[
                rgb / 255, np.ones(
                    nVertices
                )]  # make sure rgb is between [0,1] and gotta append an extra one to each row for the alpha value
            data['a_fg_color'] = 0, 0, 0, 1
            data['a_size'] = 4

            prog['u_model'] = self.model
            prog.bind(gloo.VertexBuffer(data))

        self.update()

    def set_multiview_source(self, sensor_props):
        self.nframe_total = sys.maxsize
        self.sensor_props = sensor_props

        for s in self.sensor_props:
            gl_prog = gloo.Program(VERTEX_SHADER, FRAGMENT_SHADER)
            gl_prog['u_linewidth'] = 0
            gl_prog['u_antialias'] = 0
            gl_prog['u_model'] = self.model
            gl_prog['u_view'] = self.view
            gl_prog['u_size'] = 1
            self.GL_progs[s.name] = gl_prog

            self.nframe_total = min(self.nframe_total, len(s.imgs_color))
            self.nframe_total = min(self.nframe_total, len(s.imgs_depth))
        print(self.nframe_total)
        self.apply_zoom()
        self.set_frame(0)
Beispiel #7
0
class Canvas(app.Canvas):

    visualization_modes = ['cpk', 'backbone', 'aminoacid', 'dssp']

    def __init__(self, pdbdata, mode='cpk'):

        #Startup
        app.Canvas.__init__(self, keys='interactive', size=(W, H))

        #Loading shaders
        self.program = gloo.Program(vertex, fragment)

        #Analyze pdb file
        self.parser = PDBParser(QUIET=True, PERMISSIVE=True)
        self.structure = self.parser.get_structure('model', pdbdata)

        #Mode selection
        if mode not in Canvas.visualization_modes:
            raise Exception('Not recognized visualization mode %s' % mode)
        self.mode = mode

        #Get the data of our atoms
        self.atom_information()

        #Camera settings

        self.translate = max(abs(np.concatenate(self.coordinates))) + 40
        self.translate = max(-1, self.translate)
        self.view = translate((0, 0, -self.translate), dtype=np.float32)

        self.model = np.eye(4, dtype=np.float32)
        self.projection = np.eye(4, dtype=np.float32)
        self.program['u_projection'] = self.projection

        self.quaternion = Quaternion()

        #Load data depending on the mode

        self.apply_zoom()
        self.load_data()

        #self.lines = visuals.LinePlotVisual(self.chain_coords[1], width= 5.0, marker_size= 0.0, color=self.chain_colors[1])

        gloo.set_state(depth_test=True, clear_color='white')

        self.show()

    def atom_information(self):
        """Determines the coordinates, colors and sizes of the atoms depending on the mode"""

        if self.mode == 'cpk':
            #list of atoms
            self.atoms = [atom for atom in self.structure.get_atoms()]
            self.natoms = len(self.atoms)
            #atom coordinates
            self.coordinates = np.array([atom.coord for atom in self.atoms])
            self.center = centroid(self.coordinates)
            self.coordinates -= self.center
            #atom color
            self.color = [
                np.array(colorrgba(atom.get_id())[0:3]) for atom in self.atoms
            ]
            #atom radius
            self.radius = [vrad(atom.get_id()) for atom in self.atoms]

        elif self.mode == 'aminoacid':
            #list of atoms
            self.atoms = [
                atom for atom in self.structure.get_atoms()
                if atom.get_parent().resname != 'HOH'
            ]
            self.natoms = len(self.atoms)
            #atom coordinates
            self.coordinates = np.array([atom.coord for atom in self.atoms])
            self.center = centroid(self.coordinates)
            self.coordinates -= self.center
            #atom color
            self.color = [
                colorrgba(restype(atom.get_parent().resname))[0:3]
                for atom in self.atoms
            ]
            #atom radius
            self.radius = [vrad(atom.get_id()) for atom in self.atoms]

        elif self.mode == 'backbone':
            #list of atoms
            self.atoms = [
                atom for atom in self.structure.get_atoms()
                if atom.get_name() == 'CA' or atom.get_name() == 'N'
            ]
            self.natoms = len(self.atoms)
            #atom coordinates
            self.coordinates = np.array([atom.coord for atom in self.atoms])
            self.center = centroid(self.coordinates)
            self.coordinates -= self.center
            #atom color
            self.color = []
            self.chains = []
            self.chain_coords = []
            self.chain_colors = []
            for chain in self.structure.get_chains():
                self.chains.append(chain)
                self.can_coord = np.array([
                    atom.coord for atom in chain.get_atoms()
                    if atom.get_name() == 'CA' or atom.get_name() == 'N'
                ])
                self.can_coord -= self.center
                self.chain_coords.append(self.can_coord)
                self.chain_length = len(self.can_coord)
                self.chain_color = np.random.rand(1, 3)
                self.chain_colors.append(self.chain_color)
                self.color.append(
                    np.tile(self.chain_color, (self.chain_length, 1)))
            if len(self.chains) > 1:
                self.color = np.concatenate(self.color)
            #atom radius
            self.radius = [vrad(atom.get_id()) for atom in self.atoms]

    def load_data(self):
        """Make an array with all the data and load it into VisPy Gloo"""

        data = np.zeros(self.natoms, [('a_position', np.float32, 3),
                                      ('a_color', np.float32, 3),
                                      ('a_radius', np.float32, 1)])

        data['a_position'] = self.coordinates
        data['a_color'] = self.color
        data['a_radius'] = self.radius  #*self.pixel_scale

        self.program.bind(gloo.VertexBuffer(data))

        self.program['u_model'] = self.model
        self.program['u_view'] = self.view
        self.program['u_light_position'] = 0., 0., 2.
        self.program['u_light_spec_position'] = -5., 5., -5.

        print 'Data loaded'

    def on_resize(self, event):
        width, height = event.size

    def apply_zoom(self):
        """Determine the projection of the canvas"""

        width, height = self.physical_size
        gloo.set_viewport(0, 0, width, height)
        self.projection = perspective(95.0, width / float(height), 1.0, 400.0)
        self.program['u_projection'] = self.projection

    def on_draw(self, event):
        gloo.clear()
        self.program.draw('points')
        #draw separated chains
        #if self.mode in ['backbone','dssp']:
        #for i in range(len(self.chains)):
        #self.lines = visuals.LinePlotVisual(self.chain_coords[i], width= 5.0, marker_size= 0.0, color=self.chain_colors[i])
        #self.lines.draw()

    def on_mouse_move(self, event):
        #Mouse rotation
        if event.button == 1 and event.last_event is not None:
            x0, y0 = event.last_event.pos
            x1, y1 = event.pos
            w, h = self.size
            self.quaternion = (self.quaternion *
                               Quaternion(*_arcball(x0, y0, w, h)) *
                               Quaternion(*_arcball(x1, y1, w, h)))
            self.model = self.quaternion.get_matrix()
            self.program['u_model'] = self.model
            self.update()
        #Mouse zoom
        elif event.button == 2 and event.last_event is not None:
            x0, y0 = event.last_event.pos
            x1, y1 = event.pos
            self.translate += (y1 - y0)
            self.translate = max(-1, self.translate)
            self.view = translate((0, 0, -self.translate), dtype=np.float32)
            self.program['u_view'] = self.view
            self.update()

    def on_mouse_wheel(self, event):
        self.translate -= event.delta[1]
        self.translate = max(-1, self.translate)
        self.view = translate((0, 0, -self.translate))

        self.program['u_view'] = self.view
        self.update()
Beispiel #8
0
class InteractiveViewportMixin(object):
    """ Canvas mixin for interactive rotation, translation and zooming

    This class implements on_resize, on_mouse_move, on_mouse_press,
    on_mouse_release and on_mouse_wheel in such a way that the view matrix and
    the projection matrix changes in response to user input.

    The derived class should implement on_update_view and on_update_projection
    to update the matrices in the shader.
    """
    def __init__(self, rview, zview=None, zoom_speed=0.1, move_speed=0.01):
        """ Constructor

        Parameters
        ----------
        rview : float
            Radius of inscribed sphere within the field of view.
        zview : float
            Distance to the z-clip plane from the origin.
        zoom_speed : float
            How sensitive the field of view to mouse wheel rolling.
        move_speed : float
            How sensitive the translation of view to mouse dragging.
        """
        self.rview = rview
        self.zview = zview if zview else rview
        self.zoom_speed = zoom_speed
        self.move_speed = move_speed
        self._translation = (0.0, 0.0, 0.0)
        self._quaternion = Quaternion()

    def on_update_view(self, view):
        """ Handle view matrix change
        """
        pass

    def on_update_projection(self, proj):
        """ Handle projection matrix change
        """
        pass

    def get_view_matrix(self):
        """ Return current view matrix
        """
        return np.dot(self._quaternion.get_matrix(),
                      transforms.translate(self._translation))

    def get_projection_matrix(self):
        """ Return current projection matrix
        """
        # Determine the field of view of orthographic projection so that the
        # sphere of radius rview centered at the origin inscribes the field
        # of view.
        width, height = self.physical_size
        aspect = float(width) / height
        if aspect > 1:
            top = self.rview
            right = self.rview * aspect
        else:
            top = self.rview / aspect
            right = self.rview
        assert min(top, right) == self.rview
        left = -right
        bottom = -top
        near = self.zview
        far = -self.zview

        left -= 1e-6
        right += 1e-6
        bottom -= 1e-6
        top += 1e-6
        near -= 1e-6
        far += 1e-6

        return transforms.ortho(left, right, bottom, top, near, far)

    def _update_view(self):
        self.on_update_view(self.get_view_matrix())

    def _update_projection(self):
        self.on_update_projection(self.get_projection_matrix())

    def on_resize(self, event):
        gloo.set_viewport(0, 0, *event.physical_size)
        self._update_projection()

    def on_mouse_move(self, event):
        """ Left drag to rotate, right drag to tranelate
        """
        if event.is_dragging and event.last_event:
            x0, y0 = event.last_event.pos
            x1, y1 = event.pos
            w, h = self.size

            if event.button == 1:
                self._quaternion *= arcball(x0, y0, w, h) * arcball(
                    x1, y1, w, h)
                self._update_view()

            if event.button == 2:
                tx, ty, tz = self._translation
                tx += self.move_speed * (x1 - x0)
                ty += -self.move_speed * (y1 - y0)
                self._translation = (tx, ty, tz)
                self._update_view()

    def on_mouse_wheel(self, event):
        """ Roll mouse wheel to zoom in/out
        """
        roll = event.delta[1]
        self.rview *= math.exp(-self.zoom_speed * roll)
        self._update_projection()

    def on_mouse_press(self, event):
        if event.button == 1:
            cursor = QtGui.QCursor(QtCore.Qt.ClosedHandCursor)
            QtGui.QApplication.setOverrideCursor(cursor)

        if event.button == 2:
            cursor = QtGui.QCursor(QtCore.Qt.SizeAllCursor)
            QtGui.QApplication.setOverrideCursor(cursor)

    def on_mouse_release(self, event):
        QtGui.QApplication.restoreOverrideCursor()