Source code for optimeed.visualize.gui.widgets.openGLWidget.ContextHandler

import math
import numpy as np
from OpenGL.GL import *

from . import quaternions


MODE_ZOOM = 0
MODE_ROTATION = 1
MODE_LIGHT = 2
NUMBER_OF_MODES = 3

CLIC_LEFT = 0
CLIC_RIGHT = 1


[docs]class SpecialButtonsMapping: def __init__(self): self.KEY_LEFT = None self.KEY_RIGHT = None self.KEY_UP = None self.KEY_DOWN = None self.KEY_TAB = None self.MOUSE_LEFT = None self.MOUSE_RIGHT = None
[docs]class MyText: def __init__(self, color, fontSize, theStr, windowPosition): self.color = color self.fontSize = fontSize self.position = windowPosition self.theStr = theStr
[docs]class ContextHandler: def __init__(self): self.rotation_accumulation = (1, 0, 0, 0) self.width = 200 self.height = 200 self.theDeviceDrawer = None self.theDeviceToDraw = None self.theSpecialButtonsMapping = None # Initial viewPoint and light self.__displayScale__ = False self.scaleLength = 5 self.tipAngle, self.viewAngle, self.zoomLevel = 10, 10, 40 self.must_rotate = True self.lightPosition = [-16100.0, 15900.0, 0.0, 1.0] self.backgroundColor = [0.3, 0.3, 0.3] self.centerPosition = [0, 0, 0] self.xMouseOnClic = 0 self.yMouseOnClic = 0 self.currentMode = MODE_ROTATION self.currentClic = CLIC_LEFT try: self.VP_MarginW except AttributeError: self.VP_MarginW = 0 self.VP_MarginH = 0 self.VP_W = self.width self.VP_H = self.height
[docs] def set_specialButtonsMapping(self, theSpecialButtonsMapping): self.theSpecialButtonsMapping = theSpecialButtonsMapping
[docs] def set_deviceDrawer(self, theDeviceDrawer): self.theDeviceDrawer = theDeviceDrawer
[docs] def set_deviceToDraw(self, theDeviceToDraw): if self.theDeviceToDraw is None: self.theDeviceToDraw = theDeviceToDraw _, _, self.zoomLevel = self.theDeviceDrawer.get_init_camera(self.theDeviceToDraw) else: self.theDeviceToDraw = theDeviceToDraw
[docs] def resizeWindowAction(self, new_width, new_height): ar_origin = self.width / self.height ar_new = new_width / new_height scale_w = new_width / self.width scale_h = new_height / self.height if ar_new > ar_origin: scale_w = scale_h else: scale_h = scale_w margin_x = (new_width - self.width * scale_w / ar_origin) / 2 margin_y = (new_height - self.height * scale_h) / 2 self.VP_H = int(self.height * scale_h) self.VP_W = int(self.width * scale_w / ar_origin) self.VP_MarginH = int(margin_y) self.VP_MarginW = int(margin_x)
[docs] def mouseWheelAction(self, deltaAngle): self.zoomLevel += 0.1 * self.zoomLevel * deltaAngle
# GLUT.glutPostRedisplay()
[docs] def mouseClicAction(self, button, my_x, y): self.xMouseOnClic = my_x self.yMouseOnClic = y self.currentClic = button
[docs] def mouseMotionAction(self, my_x, y): if self.currentClic == self.theSpecialButtonsMapping.MOUSE_LEFT: if self.currentMode == MODE_ROTATION: self.viewAngle = -(my_x - self.xMouseOnClic) * 0.8 self.tipAngle = -(y - self.yMouseOnClic) * 0.8 self.must_rotate = True elif self.currentMode == MODE_ZOOM: self.zoomLevel *= (1 - 0.005 * (y - self.yMouseOnClic)) elif self.currentMode == MODE_LIGHT: self.lightPosition[0] += (my_x - self.xMouseOnClic) * 100 self.lightPosition[1] += (y - self.yMouseOnClic) * 100 else: pass elif self.currentClic == self.theSpecialButtonsMapping.MOUSE_RIGHT: self.centerPosition[0] += (my_x - self.xMouseOnClic) / 1000 * 3 self.centerPosition[1] -= (y - self.yMouseOnClic) / 1000 * 3 self.xMouseOnClic = my_x self.yMouseOnClic = y
# GLUT.glutPostRedisplay()
[docs] def keyboardPushAction(self, key): # print(chr(key)) if key == ord(b'+'): self.zoomLevel += 0.1 * self.zoomLevel elif key == ord(b'-'): self.zoomLevel -= 0.1 * self.zoomLevel elif key == ord(b'M'): self.currentMode += 1 if self.currentMode >= NUMBER_OF_MODES: self.currentMode -= NUMBER_OF_MODES # elif key == b'\x1b': # self.stop = True # ScaleLength management elif key == ord(b'S'): self.__displayScale__ = not self.__displayScale__ elif key == ord(b'>'): self.scaleLength += 1 elif key == ord(b'<'): self.scaleLength -= 1 # Rotation Management elif key == self.theSpecialButtonsMapping.KEY_LEFT: self.viewAngle = -2 self.must_rotate = True elif key == self.theSpecialButtonsMapping.KEY_RIGHT: self.viewAngle = +2 self.must_rotate = True elif key == self.theSpecialButtonsMapping.KEY_UP: self.tipAngle = +2 self.must_rotate = True elif key == self.theSpecialButtonsMapping.KEY_DOWN: self.tipAngle = -2 self.must_rotate = True elif key == ord(b'X'): self.tipAngle = 0 self.viewAngle = 0 self.rotation_accumulation = (1, 0, 0, 0) self.must_rotate = True elif key == ord(b'Y'): self.tipAngle = 0 self.viewAngle = 90 self.rotation_accumulation = (1, 0, 0, 0) self.must_rotate = True elif key == ord(b'Z'): self.tipAngle = 90 self.viewAngle = 90 self.rotation_accumulation = (1, 0, 0, 0) self.must_rotate = True elif key == ord(b'R'): self.__reset__() else: self.theDeviceDrawer.keyboard_push_action(key)
[docs] def keyboardReleaseAction(self, key, my_x, y): pass
[docs] def __draw_axis__(self): if self.__displayScale__: glColor3f(*self.theDeviceDrawer.get_colour_scalebar()) glDisable(GL_LIGHTING) glDisable(GL_DEPTH_TEST) relH = 0.0 relW = 0.0 glWindowPos2f(self.VP_MarginW + self.VP_W * (1 + relW) / 2 + 4, self.VP_MarginH + self.VP_H * (1 + relH) / 2 + 4) glTranslatef(relW, relH, 0) glLineWidth(2.5) glBegin(GL_LINES) glVertex2f(0.0, 0.0) glVertex2f(self.zoomLevel / 1000 * self.scaleLength, 0.0) glEnd() glLineWidth(1.5) glBegin(GL_LINES) glVertex2f(0.0, 0.0) glVertex2f(0.0, 0.02) glVertex2f(self.zoomLevel / 1000 * self.scaleLength, 0.0) glVertex2f(self.zoomLevel / 1000 * self.scaleLength, 0.02) glEnd() # theStr = str(self.scaleLength) + 'mm' # for char in theStr: # GLUT.glutBitmapCharacter(GLUT.GLUT_BITMAP_HELVETICA_18, ord(char)) glEnable(GL_LIGHTING) glEnable(GL_DEPTH_TEST)
[docs] def redraw(self): if self.theDeviceDrawer is not None: glMatrixMode(GL_PROJECTION) glLoadIdentity() glViewport(self.VP_MarginW, self.VP_MarginH, self.VP_W, self.VP_H) # glClearDepth(1) # just for completeness background_color = self.theDeviceDrawer.get_colour_background() glClearColor(background_color[0], background_color[1], background_color[2], 1) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) # clear the screen glMatrixMode(GL_MODELVIEW) glLoadIdentity() glLightfv(GL_LIGHT0, GL_POSITION, self.lightPosition) translationMatrix = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [self.centerPosition[0], self.centerPosition[1], 0, 1]]) scaleMatrix = np.array([[self.zoomLevel, 0, 0, 0], [0, self.zoomLevel, 0, 0], [0, 0, self.zoomLevel, 0], [0, 0, 0, 1]]) # Operations on matrix if self.must_rotate: rot_y = quaternions.normalize(quaternions.axisangle_to_q((1.0, 0.0, 0.0), -self.tipAngle / 180 * math.pi)) rot_x = quaternions.normalize(quaternions.axisangle_to_q((0.0, 1.0, 0.0), -self.viewAngle / 180 * math.pi)) self.rotation_accumulation = quaternions.q_mult(self.rotation_accumulation, rot_x) self.rotation_accumulation = quaternions.q_mult(self.rotation_accumulation, rot_y) self.must_rotate = False rotationMatrix = quaternions.q_to_mat4(self.rotation_accumulation) transfo = np.matmul(scaleMatrix, np.matmul(rotationMatrix, translationMatrix)) glLoadMatrixf(transfo) if self.theDeviceToDraw is not None: self.theDeviceDrawer.draw(self.theDeviceToDraw) glLoadIdentity() self.__draw_axis__() glFlush()
[docs] def get_text_to_write(self): lineHeight = 20 fontSize = 12 textList = list() textList.append(MyText([0, 0, 0], fontSize, 'Press [ESC] to exit', [10, self.VP_H - lineHeight])) textList.append(MyText([0, 0, 0], fontSize, 'Reset: [R]', [10, self.VP_H - 2 * lineHeight])) textList.append(MyText([0, 0, 0], fontSize, 'Toggle/hide scale: [S], length control: [<] or [>]', [10, 1 * lineHeight])) textList.append(MyText([0, 0, 0], fontSize, 'Axis: [X], [Y], [Z]', [10, 2 * lineHeight])) return textList
[docs] def __lightingInit__(self): glPushMatrix() glLoadIdentity() glClearColor(self.backgroundColor[0], self.backgroundColor[1], self.backgroundColor[2], 1) glShadeModel(GL_SMOOTH) glLightfv(GL_LIGHT0, GL_POSITION, self.lightPosition) glLightfv(GL_LIGHT0, GL_SPECULAR, [6, 6, 6]) glLightfv(GL_LIGHT0, GL_AMBIENT, [3, 3, 3]) glLightfv(GL_LIGHT0, GL_DIFFUSE, [0.6, 0.6, 0.6]) glLightfv(GL_LIGHT1, GL_POSITION, [22300.0, -55800.0, 0.0, 1.0]) glLightfv(GL_LIGHT1, GL_SPECULAR, [0.8, 0.8, 0.8]) # glLightfv(GL_LIGHT1, GL_AMBIENT, [2, 2, 2]) glLightfv(GL_LIGHT1, GL_DIFFUSE, [0.4, 0.4, 0.4]) glLightfv(GL_LIGHT1, GL_LINEAR_ATTENUATION, 0) glEnable(GL_LIGHTING) glEnable(GL_LIGHT0) glEnable(GL_LIGHT1) glEnable(GL_DEPTH_TEST) glEnable(GL_NORMALIZE) glPopMatrix()
[docs] def initialize(self): self.__lightingInit__() self.theDeviceDrawer.get_opengl_options() self.tipAngle, self.viewAngle, self.zoomLevel = self.theDeviceDrawer.get_init_camera(self.theDeviceToDraw)
[docs] def __reset__(self): deviceDrawer = self.theDeviceDrawer deviceToDraw = self.theDeviceToDraw keymap = self.theSpecialButtonsMapping self.__init__() self.set_deviceDrawer(deviceDrawer) self.set_deviceToDraw(deviceToDraw) self.set_specialButtonsMapping(keymap)