#!/usr/bin/python2.7 # -*- coding: utf-8 -*-\ ''' Window for defining electrode proprieties Part of the main SimNIBS GUI This program is part of the SimNIBS package. Please check on www.simnibs.org how to cite our work in publications. Copyright (C) 2018 Guilherme B Saturnino This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. ''' from PyQt5 import QtCore, QtGui, QtWidgets from OpenGL import GL, GLU import math import copy import sys import numpy from ..simulation import sim_struct class Ui_Electrode(QtWidgets.QDialog): def __init__(self, electrode_struct): super(Ui_Electrode, self).__init__() self.electrode_struct = copy.deepcopy(electrode_struct) mainLayout = QtWidgets.QGridLayout() self.glElectrode = GLElectrode() self.set_shape_size_layout() self.set_connector_layout() self.set_type_tick_layout() self.button_box = QtWidgets.QDialogButtonBox(QtWidgets.QDialogButtonBox.Ok|QtWidgets.QDialogButtonBox.Cancel) self.button_box.accepted.connect(self.checkAndAccept) #self.button_box.accepted.connect(self.accept) self.button_box.rejected.connect(self.reject) mainLayout.addWidget(self.shape_size, 0,4) mainLayout.addWidget(self.type_thick, 1,4) mainLayout.addWidget(self.connector_box,2,4) mainLayout.addWidget(self.glElectrode,0,0,4,4) mainLayout.addWidget(self.button_box, 4,4) self.update_electrode() self.glElectrode.electrode_object, self.glElectrode.plug_object = self.glElectrode.drawElectrode(self.electrode_struct) self.glElectrode.electrode_struct = self.electrode_struct self.glElectrode.update() self.setLayout(mainLayout) self.resize(900,450) self.setWindowTitle('Electrode') #Shape and size box def set_shape_size_layout(self): self.shape_size = QtWidgets.QGroupBox("Shape and Size") layout = QtWidgets.QGridLayout() self.shape_selector = QtWidgets.QComboBox() self.shape_selector.addItem("Rectangular") self.shape_selector.addItem("Elliptical") if self.electrode_struct.shape == 'ellipse': self.shape_selector.setCurrentIndex(1) self.shape_selector.activated.connect(self.update_electrode) layout.addWidget(self.shape_selector,0,0) self.dim_x = QtWidgets.QDoubleSpinBox() if self.electrode_struct.dimensions is not None: self.dim_x.setValue(self.electrode_struct.dimensions[0]/10.0) else: self.dim_x.setValue(5.0) self.dim_x.setSuffix(" cm") self.dim_x.setSingleStep(0.5) self.dim_x.setMinimum(0.5) layout.addWidget(self.dim_x, 0, 1) self.dim_x.valueChanged.connect(self.update_electrode) self.dim_y = QtWidgets.QDoubleSpinBox() if self.electrode_struct.dimensions is not None: self.dim_y.setValue(self.electrode_struct.dimensions[1]/10) else: self.dim_y.setValue(5.0) self.dim_y.setSuffix(" cm") self.dim_y.setSingleStep(0.5) self.dim_y.setMinimum(0.5) layout.addWidget(self.dim_y, 0, 2) self.dim_y.valueChanged.connect(self.update_electrode) self.shape_size.setLayout(layout) #Type and thickness box def set_type_tick_layout(self): self.type_thick = QtWidgets.QGroupBox("Type and Thickness") layout = QtWidgets.QGridLayout() self.type_selector = QtWidgets.QComboBox() self.type_selector.addItem("Simple") self.type_selector.addItem("Electrode+Gel") self.type_selector.addItem("Electrode+Sponge") if len(self.electrode_struct.thickness) == 2: self.type_selector.setCurrentIndex(1) if len(self.electrode_struct.thickness) == 3: self.type_selector.setCurrentIndex(2) self.type_selector.activated.connect(self.update_labels) self.type_selector.activated.connect(self.update_electrode) layout.addWidget(self.type_selector,0,0,1,2) self.label_thick1= QtWidgets.QLabel("Electrode Thickness:") layout.addWidget(self.label_thick1, 1, 0,1,1) self.thick1 = QtWidgets.QDoubleSpinBox() if len(self.electrode_struct.thickness) == 1: self.thick1.setValue(self.electrode_struct.thickness[0]) if len(self.electrode_struct.thickness) == 2 or len(self.electrode_struct.thickness) == 3: self.thick1.setValue(self.electrode_struct.thickness[1]) self.thick1.valueChanged.connect(self.update_electrode) self.thick1.setSuffix(" mm") self.thick1.setSingleStep(0.5) layout.addWidget(self.thick1,1,1,1,1) self.label_thick2= QtWidgets.QLabel("Gel/Sponge Thickness:") layout.addWidget(self.label_thick2, 2, 0,1,1) self.thick2 = QtWidgets.QDoubleSpinBox() if len(self.electrode_struct.thickness) == 2: self.thick2.setValue(self.electrode_struct.thickness[0]) if len(self.electrode_struct.thickness) == 3: self.thick2.setValue(2*self.electrode_struct.thickness[0]) if len(self.electrode_struct.thickness) == 0: self.thick1.setValue(5.0) self.thick2.setValue(5.0) self.thick2.valueChanged.connect(self.update_electrode) self.thick2.setSuffix(" mm") self.thick2.setSingleStep(0.5) layout.addWidget(self.thick2,2,1,1,1) self.label_sporatio= QtWidgets.QLabel("Electrode/Sponge size:") layout.addWidget(self.label_sporatio, 3, 0,1,1) self.spo_x = QtWidgets.QDoubleSpinBox() self.spo_x.setMinimum(1.0 * self.dim_x.value()) self.spo_x.setSingleStep(0.5) layout.addWidget(self.spo_x,3,1,1,1) self.spo_y = QtWidgets.QDoubleSpinBox() self.spo_y.setMinimum(1.0 * self.dim_y.value()) self.spo_y.setSingleStep(0.5) layout.addWidget(self.spo_y,3,2,1,1) if len(self.electrode_struct.thickness) == 3 and\ self.electrode_struct.dimensions_sponge is not None: self.spo_x.setValue(self.electrode_struct.dimensions_sponge[0] / 10.) self.spo_y.setValue(self.electrode_struct.dimensions_sponge[1] / 10.) self.spo_y.valueChanged.connect(self.update_electrode) self.spo_x.valueChanged.connect(self.update_electrode) self.update_labels() self.type_thick.setLayout(layout) #Box for defining connector proprieties def set_connector_layout(self): self.connector_box = QtWidgets.QGroupBox("Connector information") layout1 = QtWidgets.QGridLayout() has_connector = False if len(self.electrode_struct.plug) == 1: has_connector = True self.No_Connector = QtWidgets.QRadioButton("Whole Surface") if not(has_connector): self.No_Connector.toggle() self.No_Connector.toggled.connect(self.enable_disable_connector) self.No_Connector.toggled.connect(self.update_electrode) layout1.addWidget(self.No_Connector, 0, 0,1,1) self.Yes_Connector = QtWidgets.QRadioButton("Define Connector") if (has_connector): self.Yes_Connector.toggle() self.Yes_Connector.toggled.connect(self.enable_disable_connector) self.Yes_Connector.toggled.connect(self.update_electrode) layout1.addWidget(self.Yes_Connector, 0, 1,1,1) self.label_con_pos = QtWidgets.QLabel("Position in relation to electrode center:") layout1.addWidget(self.label_con_pos, 1, 0,1,3) self.con_position_x = QtWidgets.QDoubleSpinBox() self.con_position_x.setMinimum(-20.0) if has_connector: self.con_position_x.setValue(self.electrode_struct.plug[0].centre[0]/10.0) self.con_position_x.valueChanged.connect(self.update_electrode) self.con_position_x.setSingleStep(0.5) layout1.addWidget(self.con_position_x,2,0) self.con_position_y = QtWidgets.QDoubleSpinBox() self.con_position_y.setMinimum(-20.0) if has_connector: self.con_position_y.setValue(self.electrode_struct.plug[0].centre[1]/10.0) self.con_position_y.valueChanged.connect(self.update_electrode) self.con_position_y.setSingleStep(0.5) layout1.addWidget(self.con_position_y,2,1) self.label_con_shape = QtWidgets.QLabel("Shape:") layout1.addWidget(self.label_con_shape, 3, 0) self.con_shape_selector = QtWidgets.QComboBox() self.con_shape_selector.addItem("Rectangular") self.con_shape_selector.addItem("Elliptical") if has_connector: if self.electrode_struct.plug[0].shape == 'ellipse': self.con_shape_selector.setCurrentIndex(1) self.con_shape_selector.activated.connect(self.update_electrode) layout1.addWidget(self.con_shape_selector,4,0) self.con_dim_x = QtWidgets.QDoubleSpinBox() if has_connector: self.con_dim_x.setValue(self.electrode_struct.plug[0].dimensions[0]/10.0) else: self.con_dim_x.setValue(2.0) self.con_dim_x.valueChanged.connect(self.update_electrode) self.con_dim_x.setSuffix(" cm") self.con_dim_x.setSingleStep(0.5) self.con_dim_x.setMinimum(0.5) layout1.addWidget(self.con_dim_x, 4, 1) self.con_dim_y = QtWidgets.QDoubleSpinBox() if has_connector: self.con_dim_y.setValue(self.electrode_struct.plug[0].dimensions[1]/10.0) else: self.con_dim_y.setValue(1.0) self.con_dim_y.valueChanged.connect(self.update_electrode) self.con_dim_y.setSuffix(" cm") self.con_dim_y.setSingleStep(0.5) self.con_dim_y.setMinimum(0.5) layout1.addWidget(self.con_dim_y, 4, 2) self.enable_disable_connector() self.connector_box.setLayout(layout1) #Updates electrode structure and OpenGL model def update_electrode(self) : if self.shape_selector.currentIndex() == 0: self.electrode_struct.definition = 'plane' self.electrode_struct.shape = 'rect' if self.shape_selector.currentIndex() == 1: self.electrode_struct.definition = 'plane' self.electrode_struct.shape = 'ellipse' #write dimensions self.electrode_struct.dimensions = [self.dim_x.value()*10, self.dim_y.value()*10] #write thickness, for different electrode types #electrode in sponge if self.type_selector.currentIndex() == 2: self.electrode_struct.thickness = [0.0,0.0,0.0] self.electrode_struct.thickness[0] = self.thick2.value()/2.0 self.electrode_struct.thickness[1] = self.thick1.value() self.electrode_struct.thickness[2] = self.thick2.value()/2.0 self.electrode_struct.dimensions_sponge = [self.spo_x.value() * 10, self.spo_y.value() * 10] self.spo_x.setMinimum(1.0 * self.dim_x.value()) self.spo_y.setMinimum(1.0 * self.dim_y.value()) self.dim_x.setMaximum(1./1.0 * self.spo_x.value()) self.dim_y.setMaximum(1./1.0 * self.spo_y.value()) #electrode+gel if self.type_selector.currentIndex() == 1: self.electrode_struct.thickness = [0.0,0.0] self.electrode_struct.thickness[0] = self.thick2.value() self.electrode_struct.thickness[1] = self.thick1.value() self.electrode_struct.dimensions_sponge = None #simple if self.type_selector.currentIndex() == 0: self.electrode_struct.thickness = [0.0] self.electrode_struct.thickness[0] = self.thick1.value() self.electrode_struct.dimensions_sponge = None ##connector if self.Yes_Connector.isChecked(): if len(self.electrode_struct.plug) == 0 : self.electrode_struct.plug.append(sim_struct.ELECTRODE()) if self.con_shape_selector.currentIndex() == 0: self.electrode_struct.plug[0].definition = 'plane' self.electrode_struct.plug[0].shape = 'rect' if self.con_shape_selector.currentIndex() == 1: self.electrode_struct.plug[0].definition = 'plane' self.electrode_struct.plug[0].shape = 'ellipse' self.electrode_struct.plug[0].dimensions = [self.con_dim_x.value()*10, self.con_dim_y.value()*10] self.electrode_struct.plug[0].centre = [0.0,0.0] self.electrode_struct.plug[0].centre[0]= self.con_position_x.value()*10 self.electrode_struct.plug[0].centre[1]= self.con_position_y.value()*10 if self.No_Connector.isChecked(): self.electrode_struct.plug = [] self.glElectrode.electrode_object, self.glElectrode.plug_object= self.glElectrode.drawElectrode(self.electrode_struct) self.glElectrode.electrode_struct = self.electrode_struct self.glElectrode.update() QtWidgets.QApplication.processEvents() def update_labels(self): if self.type_selector.currentIndex() == 0: self.thick2.setEnabled(False) self.label_thick2.setEnabled(False) self.spo_x.setEnabled(False) self.spo_y.setEnabled(False) self.label_sporatio.setEnabled(False) if self.electrode_struct.thickness is not None and\ len(self.electrode_struct.thickness) == 1: self.thick1.setValue(self.electrode_struct.thickness[0]) else: self.thick1.setValue(5.00) self.thick2.setValue(0.00) self.spo_x.setValue(0) self.spo_y.setValue(0) if self.type_selector.currentIndex() == 1: self.thick2.setEnabled(True) self.label_thick2.setEnabled(True) self.spo_x.setEnabled(False) self.spo_y.setEnabled(False) self.label_sporatio.setEnabled(False) if self.electrode_struct.thickness is not None and\ len(self.electrode_struct.thickness) == 2: self.thick2.setValue(self.electrode_struct.thickness[0]) self.thick1.setValue(self.electrode_struct.thickness[1]) else: self.thick1.setValue(1.00) self.thick2.setValue(5.00) self.spo_x.setValue(0.0) self.spo_y.setValue(0.0) if self.type_selector.currentIndex() == 2: self.thick2.setEnabled(True) self.label_thick2.setEnabled(True) self.spo_x.setEnabled(True) self.spo_y.setEnabled(True) self.label_sporatio.setEnabled(True) if self.electrode_struct.thickness is not None and\ len(self.electrode_struct.thickness) == 3: self.thick2.setValue(self.electrode_struct.thickness[0] * 2) self.thick1.setValue(self.electrode_struct.thickness[1]) else: self.thick1.setValue(1.00) self.thick2.setValue(8.00) self.spo_x.setMinimum(1.0 * self.dim_x.value()) self.spo_y.setMinimum(1.0 * self.dim_y.value()) self.dim_x.setMaximum(1./1.0 * self.spo_x.value()) self.dim_y.setMaximum(1./1.0 * self.spo_y.value()) #Disable/enable things envolving the connector def enable_disable_connector(self): has_con = self.Yes_Connector.isChecked() self.con_position_x.setEnabled(has_con) self.con_position_y.setEnabled(has_con) self.con_dim_x.setEnabled(has_con) self.con_dim_y.setEnabled(has_con) self.con_shape_selector.setEnabled(has_con) self.label_con_pos.setEnabled(has_con) self.label_con_shape.setEnabled(has_con) #checks if connector is completelly inside the electrode def checkAndAccept(self): ''' if len(self.electrode_struct.plug) == 1: if abs(self.electrode_struct.plug[0].centre[0])+self.electrode_struct.plug[0].dimX/2.0 > self.electrode_struct.dimX/2.0: reply = QtWidgets.QMessageBox.critical(self, "Warning", "Plug outside electrode in X dimension") return None elif abs(self.electrode_struct.plug[0].centre[1])+self.electrode_struct.plug[0].dimY/2.0 > self.electrode_struct.dimY/2.0: reply = QtWidgets.QMessageBox.critical(self, "Warning", "Plug outside electrode in Y dimension") return None ''' self.accept() #Returns electrode structure def return_el_struct(self): dialog = Ui_Electrode(self.electrode_struct) result = dialog.exec_() struct = dialog.electrode_struct return (struct, result == QtWidgets.QDialog.Accepted) ##################################################################### ############Electrode OpenGL Model################################### ##################################################################### class GLElectrode(QtWidgets.QOpenGLWidget): def __init__(self, parent=None): super(GLElectrode, self).__init__(parent) self.electrode_object = 0 self.plug_object = 0 self.center_dir = 0 self.xRot = 3160 self.yRot = 5536 self.zRot = 0 self.zoom = 1.0 self.electrode_placeholder = sim_struct.ELECTRODE() self.electrode_placeholder.dimensions = [0.0, 0.0] self.electrode_placeholder.thickness = [0.0] self.lastPos = QtCore.QPoint() def minimumSizeHint(self): return QtCore.QSize(50, 50) def sizeHint(self): return QtCore.QSize(450, 450) def setXRotation(self, angle): angle = self.normalizeAngle(angle) if angle != self.xRot: self.xRot = angle #self.emit(QtCore.SIGNAL("xRotationChanged(int)"), angle) self.update() def setYRotation(self, angle): angle = self.normalizeAngle(angle) if angle != self.yRot: self.yRot = angle #self.emit(QtCore.SIGNAL("yRotationChanged(int)"), angle) self.update() def setZRotation(self, angle): angle = self.normalizeAngle(angle) if angle != self.zRot: self.zRot = angle #self.emit(QtCore.SIGNAL("zRotationChanged(int)"), angle) self.update() def setClearColor(self, c): GL.glClearColor(c.redF(), c.greenF(), c.blueF(), c.alphaF()) def initializeGL(self): self.setClearColor(QtGui.QColor.fromCmykF(0.1, .0, 0.2, 1.0)) self.electrode_object, self.plug_object = \ self.drawElectrode(self.electrode_struct) self.center_dir = self.drawPointAndDirs() GL.glShadeModel(GL.GL_FLAT) GL.glEnable(GL.GL_DEPTH_TEST) def paintGL(self): GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT) GL.glLoadIdentity() GL.glTranslated(0.0, 0.0, -10.0) GL.glRotated(self.xRot / 16.0, 1.0, 0.0, 0.0) GL.glRotated(self.yRot / 16.0, 0.0, 1.0, 0.0) GL.glRotated(self.zRot / 16.0, 0.0, 0.0, 1.0) GL.glScalef(self.zoom,self.zoom,self.zoom) GL.glCallList(self.electrode_object) GL.glCallList(self.center_dir) if self.plug_object != 0: GL.glCallList(self.plug_object) def resizeGL(self, width, height): side = min(width, height) GL.glViewport((width - side) // 2, (height - side) // 2, side, side) GL.glMatrixMode(GL.GL_PROJECTION) GL.glLoadIdentity() #GL.glOrtho(-0.5, +0.5, +0.5, -0.5, 4.0, 15.0) GL.glFrustum(-0.5, +0.5, +0.5, -0.5, 4.0, 15.0) GL.glMatrixMode(GL.GL_MODELVIEW) def mousePressEvent(self, event): self.lastPos = QtCore.QPoint(event.pos()) def mouseMoveEvent(self, event): dx = event.x() - self.lastPos.x() dy = event.y() - self.lastPos.y() if event.buttons() & QtCore.Qt.LeftButton: self.setXRotation(self.xRot - 8 * dy) self.setYRotation(self.yRot - 8 * dx) elif event.buttons() & QtCore.Qt.RightButton: self.setXRotation(self.xRot - 8 * dy) self.setZRotation(self.zRot - 8 * dx) self.lastPos = QtCore.QPoint(event.pos()) def wheelEvent(self, event): delta = event.angleDelta().y() zoom = self.zoom+delta/1200.0 if zoom > 0.1 and zoom < 10: self.zoom = zoom self.update() def drawElectrode(self, electrode_struct): yellow = QtGui.QColor.fromCmykF(0.00, 0.0, 1.0, 0.0) grey = QtGui.QColor.fromCmykF(0.00, 0.0, 0.0, 0.7) blue = QtGui.QColor.fromCmykF(0.83, 0.54, 0.0, 0.0) red = QtGui.QColor.fromCmykF(0.00, 0.99, 1.0, 0.0) scale = 0.02 try: size_x = electrode_struct.dimensions[0] * scale except: size_x = 0 try: size_y = electrode_struct.dimensions[1] * scale except: size_y = 0 thick1 = 0 thick2 = 0 thick_sponge = 0 z_center = 0 model = '' if len(electrode_struct.thickness) == 1: thick1 = electrode_struct.thickness[0]*scale model = 'simple' if len(electrode_struct.thickness) == 2: thick1 = electrode_struct.thickness[1]*scale thick2 = electrode_struct.thickness[0]*scale model = '2layer' if len(electrode_struct.thickness) == 3: thick1 = electrode_struct.thickness[1]*scale thick2 = electrode_struct.thickness[0]*scale + \ electrode_struct.thickness[1]*scale + electrode_struct.thickness[2]*scale model = 'sponge' electrode_list = GL.glGenLists(1) GL.glNewList(electrode_list, GL.GL_COMPILE) if electrode_struct.shape == 'rect': if model == 'simple' : self.cuboid(0,0,0,size_x,size_y,thick1,blue, False) if model == '2layer' and thick2 > 0: self.cuboid(0,0,0,size_x,size_y,thick1,grey, False) self.cuboid(0,0,(thick1+thick2)/2,size_x,size_y,thick2,blue, False) if model == 'sponge': self.cuboid(0,0,0,size_x,size_y,thick1,grey, False) sponge_size_x = electrode_struct.dimensions_sponge[0] * scale sponge_size_y = electrode_struct.dimensions_sponge[1] * scale self.cuboid(0,0,0,sponge_size_x,sponge_size_y,thick2,yellow, True) if electrode_struct.shape == 'ellipse': if model == 'simple' : self.cylinder(0,0,0,size_x,size_y,thick1,blue, False) if model == '2layer' and thick2 > 0: self.cylinder(0,0,0,size_x,size_y,thick1,grey, False) self.cylinder(0,0,(thick1+thick2)/2,size_x,size_y,thick2,blue, False) if model == 'sponge': self.cylinder(0,0,0,size_x,size_y,thick1,grey, False) sponge_size_x = electrode_struct.dimensions_sponge[0] * scale sponge_size_y = electrode_struct.dimensions_sponge[1] * scale self.cylinder(0,0,0,sponge_size_x,sponge_size_y,thick2,yellow, True) GL.glEndList() plug_list = GL.glGenLists(1) GL.glNewList(plug_list, GL.GL_COMPILE) ##Model Plug if len(electrode_struct.plug) > 0 : con_size_x = electrode_struct.plug[0].dimensions[0]*scale con_size_y = electrode_struct.plug[0].dimensions[1]*scale con_center_x = electrode_struct.plug[0].centre[0]*scale con_center_y = electrode_struct.plug[0].centre[1]*scale dz = 0.001 if electrode_struct.plug[0].shape == 'rect': self.plane_xy(con_center_x, con_center_y, -(thick1/2+dz), con_size_x, con_size_y, red) if electrode_struct.plug[0].shape == 'ellipse': self.ellipse_xy(con_center_x, con_center_y, -(thick1/2+dz), con_size_x, con_size_y, red) GL.glEndList() return electrode_list, plug_list def qglColor(self, c): GL.glColor3f(c.redF(), c.greenF(), c.blueF()) def cuboid(self, center_x, center_y,center_z, size_x, size_y, size_z, color, wireframe): if wireframe : GL.glPolygonMode( GL.GL_FRONT_AND_BACK, GL.GL_LINE ) GL.glBegin(GL.GL_QUADS) self.qglColor(color) px = center_x+size_x/2 mx =center_x-size_x/2 py = center_y+size_y/2 my =center_y-size_y/2 pz = center_z+size_z/2 mz =center_z-size_z/2 GL.glVertex3d(px,py, pz) GL.glVertex3d(px,my, pz) GL.glVertex3d(mx,my, pz) GL.glVertex3d(mx,py, pz) GL.glVertex3d(px,py, mz) GL.glVertex3d(mx,py, mz) GL.glVertex3d(mx,my, mz) GL.glVertex3d(px,my, mz) self.qglColor(color.darker(250)) GL.glVertex3d(px,py, pz) GL.glVertex3d(mx,py, pz) GL.glVertex3d(mx,py, mz) GL.glVertex3d(px,py, mz) GL.glVertex3d(px,my, pz) GL.glVertex3d(mx,my, pz) GL.glVertex3d(mx,my, mz) GL.glVertex3d(px,my, mz) GL.glVertex3d(px,py, pz) GL.glVertex3d(px,my, pz) GL.glVertex3d(px,my, mz) GL.glVertex3d(px,py, mz) GL.glVertex3d(mx,py, pz) GL.glVertex3d(mx,my, pz) GL.glVertex3d(mx,my, mz) GL.glVertex3d(mx,py, mz) GL.glEnd() if wireframe: GL.glPolygonMode( GL.GL_FRONT_AND_BACK, GL.GL_FILL ); def cylinder(self, center_x,center_y, center_z, x_axis, y_axis, size_z, color, wireframe) : Pi = 3.14159265358979323846 if wireframe: nbr_sides = 18 else: nbr_sides = 100 pz = center_z+size_z/2 mz = center_z-size_z/2 #top if wireframe : GL.glPolygonMode( GL.GL_FRONT_AND_BACK, GL.GL_LINE ) GL.glBegin(GL.GL_POLYGON) self.qglColor(color) for i in range(nbr_sides): angle1 = (i * 2 * Pi) / nbr_sides x1 = center_x + x_axis/2 * math.sin(angle1) y1 = center_y + y_axis/2 * math.cos(angle1) GL.glVertex3d(x1, y1, pz) GL.glEnd() #bottom GL.glBegin(GL.GL_POLYGON) self.qglColor(color) for i in range(nbr_sides): angle1 = (i * 2 * Pi) / nbr_sides x1 = center_x + x_axis/2 * math.sin(angle1) y1 = center_y + y_axis/2 * math.cos(angle1) GL.glVertex3d(x1, y1, mz) GL.glEnd() #Sides GL.glBegin(GL.GL_QUADS) self.qglColor(color.darker(250)) for i in range(nbr_sides): angle1 = (i * 2 * Pi) / nbr_sides angle2 = ((i+1) * 2 * Pi) / nbr_sides x1 = center_x + x_axis/2 * math.sin(angle1) y1 = center_y + y_axis/2 * math.cos(angle1) x2 = center_x + x_axis/2 * math.sin(angle2) y2 = center_y + y_axis/2 * math.cos(angle2) GL.glVertex3d(x1, y1, pz) GL.glVertex3d(x1, y1, mz) GL.glVertex3d(x2, y2, mz) GL.glVertex3d(x2, y2, pz) GL.glEnd() #if wireframe: lines in top and bottom if wireframe: GL.glBegin(GL.GL_LINES) self.qglColor(color) for i in range(nbr_sides//2): angle1 = (i * 2 * Pi) / nbr_sides angle2 = (i * 2 * Pi) / nbr_sides + Pi x1 = center_x + x_axis/2 * math.sin(angle1) y1 = center_y + y_axis/2 * math.cos(angle1) x2 = center_x + x_axis/2 * math.sin(angle2) y2 = center_y + y_axis/2 * math.cos(angle2) GL.glVertex3d(x1, y1, pz) GL.glVertex3d(x2, y2, pz) GL.glVertex3d(x1, y1, mz) GL.glVertex3d(x2, y2, mz) GL.glEnd() if wireframe: GL.glPolygonMode( GL.GL_FRONT_AND_BACK, GL.GL_FILL ); def plane_xy (self, center_x,center_y, center_z, size_x, size_y,color) : GL.glBegin(GL.GL_QUADS) self.qglColor(color) px = center_x+size_x/2 mx =center_x-size_x/2 py = center_y+size_y/2 my =center_y-size_y/2 GL.glVertex3d(px,py, center_z) GL.glVertex3d(mx,py, center_z) GL.glVertex3d(mx,my, center_z) GL.glVertex3d(px,my, center_z) GL.glEnd() def ellipse_xy (self, center_x, center_y, center_z, x_axis, y_axis, color): Pi = 3.14159265358979323846 nbr_sides = 100 GL.glBegin(GL.GL_POLYGON) self.qglColor(color) for i in range(nbr_sides): angle1 = (i * 2 * Pi) / nbr_sides x1 = center_x + x_axis/2 * math.sin(angle1) y1 = center_y + y_axis/2 * math.cos(angle1) GL.glVertex3d(x1, y1, center_z) GL.glEnd() def normalizeAngle(self, angle): while angle < 0: angle += 360 * 16 while angle > 360 * 16: angle -= 360 * 16 return angle def drawPointAndDirs(self): xAxis = numpy.array([1,0,0], 'float') yAxis = numpy.array([0,1,0], 'float') zAxis = numpy.array([0,0,1], 'float') center =numpy.array([0,0,0], 'float') qobj = GLU.gluNewQuadric() sphere_radius = 0.1 cyl_height = 1 cyl_radius = 0.01 z_dir = numpy.array([0.,0.,1.], dtype = 'float64') genList = GL.glGenLists(1) GL.glNewList(genList, GL.GL_COMPILE) #Cylinder along z, we want it to be allong xAxis #Solution: use the appropriate rotation matrix #We have to choose the right axis, perpendicular to both, and rotate by the appropriate angle, the angle between the 2 vectors self.qglColor(QtGui.QColor.fromCmykF(0., 1., 1., 0.)) rotation_dir = numpy.cross(z_dir,xAxis) angle = math.acos(z_dir.dot(xAxis))*180/3.14159 GL.glPushMatrix() GL.glTranslatef(center[0],center[1],center[2]) GL.glRotatef(angle, rotation_dir[0],rotation_dir[1],rotation_dir[2]) GLU.gluCylinder(qobj,cyl_radius,cyl_radius,cyl_height,20,20) GL.glPopMatrix() self.qglColor(QtGui.QColor.fromCmykF(1., 0., 1., 0.)) rotation_dir = numpy.cross(z_dir,yAxis) angle = math.acos(z_dir.dot(yAxis))*180/3.14159 GL.glPushMatrix() GL.glTranslatef(center[0],center[1],center[2]) GL.glRotatef(angle, rotation_dir[0],rotation_dir[1],rotation_dir[2]) GLU.gluCylinder(qobj,cyl_radius,cyl_radius,cyl_height,20,20) GL.glPopMatrix() GL.glEndList() return genList if __name__ == '__main__': app = QtWidgets.QApplication(sys.argv) electrode_struct = sim_struct.ELECTRODE() ex = Ui_Electrode(electrode_struct) ex.show() sys.exit(app.exec_())