Wed 28 Aug 21:38:52 CEST 2024
This commit is contained in:
		
							parent
							
								
									2d6dd151a6
								
							
						
					
					
						commit
						b8a1154a2a
					
				
							
								
								
									
										362
									
								
								src/SimNDT/graphics/glWidget.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										362
									
								
								src/SimNDT/graphics/glWidget.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,362 @@ | ||||||
|  | 
 | ||||||
|  | import sys | ||||||
|  | from PySide.QtCore	import * | ||||||
|  | from PySide.QtGui import * | ||||||
|  | from PySide.QtOpenGL import * | ||||||
|  | 
 | ||||||
|  | import math | ||||||
|  | import numpy as	 np | ||||||
|  | import OpenGL.GL as GL | ||||||
|  | import platform | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | import glumpy | ||||||
|  | import colormaps | ||||||
|  | 
 | ||||||
|  | import SimNDT.gui.HelperMethods  as HelperMethods | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def mapValue(data,in_min,in_max,out_min,out_max): | ||||||
|  | 	return (data-in_min)*(out_max-out_min)/(in_max-in_min) + out_min | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class RefreshZoom(QObject): | ||||||
|  | 
 | ||||||
|  | 	zoomed = Signal(int) | ||||||
|  | 
 | ||||||
|  | 	def __init__(self): | ||||||
|  | 		QObject.__init__(self) | ||||||
|  | 
 | ||||||
|  | 	def zoom(self, value): | ||||||
|  | 		self.zoomed.emit(value) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class GLWidget(QGLWidget): | ||||||
|  | 	 | ||||||
|  | 	 | ||||||
|  | 	def __init__(self, parent=None, width=600, height=600): | ||||||
|  | 
 | ||||||
|  | 		self.parent = parent | ||||||
|  | 		self._width, self._height = width, height | ||||||
|  | 		QGLWidget.__init__(self, QGLFormat(QGL.SampleBuffers), parent) | ||||||
|  | 
 | ||||||
|  | 		self.setAttribute(Qt.WA_NoSystemBackground) | ||||||
|  | 		self.refreshZoom = RefreshZoom() | ||||||
|  | 		self.setContextMenuPolicy(Qt.CustomContextMenu) | ||||||
|  | 		self.customContextMenuRequested.connect(self.showContextMenu) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 		self.cmap_jet = colormaps.CMAP_JET | ||||||
|  | 		self.cmap_gray = colormaps.CMAP_GRAY | ||||||
|  | 		self.cmap_arcoiris = colormaps.CMAP_RAINBOW | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 		self._Starting = False | ||||||
|  | 		self.Enable = False | ||||||
|  | 		 | ||||||
|  | 		self._x = self._width/2.0 | ||||||
|  | 		self._y	= self._height/2.0 | ||||||
|  | 		self._zoom = 0.3 | ||||||
|  | 		 | ||||||
|  | 		self.Offset = QPoint() | ||||||
|  | 		self.ActualPosition = QPoint() | ||||||
|  | 		self.DragStart = QPoint() | ||||||
|  | 		self.newOffset= QPoint() | ||||||
|  | 		self._dx = 0 | ||||||
|  | 		self._dy = 0 | ||||||
|  | 		 | ||||||
|  | 		self.image = None | ||||||
|  | 		self._ImageSim = False | ||||||
|  | 		 | ||||||
|  | 		self.EnableTransducers = False | ||||||
|  | 		self._ABS = False | ||||||
|  | 
 | ||||||
|  | 		self.cmap = self.cmap_jet | ||||||
|  | 		 | ||||||
|  | 	def init(self): | ||||||
|  | 		 | ||||||
|  | 		self.resizeGL(self._width,self._height) | ||||||
|  | 		self.initializeGL() | ||||||
|  | 
 | ||||||
|  | 	def disable(self): | ||||||
|  | 		self._Starting	= False | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	def showContextMenu(self, pos): | ||||||
|  | 
 | ||||||
|  | 		menu = QMenu() | ||||||
|  | 		HelperMethods.addActions(menu, self.parent.actionAdd_Ellipse) | ||||||
|  | 		HelperMethods.addActions(menu, self.parent.actionAdd_Rectangle) | ||||||
|  | 		menu.exec_(self.mapToGlobal(pos)) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	def setColormap(self,value): | ||||||
|  | 
 | ||||||
|  | 		if value == 0: | ||||||
|  | 			self.cmap = self.cmap_jet | ||||||
|  | 		elif value == 1: | ||||||
|  | 			self.cmap = self.cmap_gray | ||||||
|  | 
 | ||||||
|  | 	def setImage(self,I, DB = 60): | ||||||
|  | 		 | ||||||
|  | 		self.DB   = DB | ||||||
|  | 		self.time = 0		 | ||||||
|  | 		 | ||||||
|  | 		self._Starting	= True | ||||||
|  | 		I = np.float32(I) | ||||||
|  | 		self.Z		=  I | ||||||
|  | 		self.image	= [] | ||||||
|  | 		self.image	= glumpy.image.Image(self.Z, interpolation='bilinear', | ||||||
|  | 												 colormap=self.cmap, | ||||||
|  | 												 vmin= -self.DB, vmax=0) | ||||||
|  | 
 | ||||||
|  | 		C = np.linspace(-self.DB,0,256).astype(np.float32) | ||||||
|  | 		C = C.reshape((1,256)) | ||||||
|  | 		self.colorbar = glumpy.image.Image(C, colormap=self.cmap) | ||||||
|  | 		 | ||||||
|  | 		self._ImageSim = True | ||||||
|  | 		self.values_text = np.linspace(-self.DB,0,10, endpoint=True) | ||||||
|  | 		self.tick  = [mapValue(i,-self.DB,0,0,self._width-10) for i in self.values_text] | ||||||
|  | 		 | ||||||
|  | 	 | ||||||
|  | 	def updateWithImage(self,I, time): | ||||||
|  | 		self.M,self.N = np.shape(I) | ||||||
|  | 		self.time = time | ||||||
|  | 		self.Z[...] =  I | ||||||
|  | 		self.image.update() | ||||||
|  | 		self.updateGL() | ||||||
|  | 	 | ||||||
|  | 
 | ||||||
|  | 	def imshow(self, I): | ||||||
|  | 		 | ||||||
|  | 		self._ImageSim = False | ||||||
|  | 		I = np.float32(I) | ||||||
|  | 		self.M, self.N = np.shape(I) | ||||||
|  | 		self.image	  = [] | ||||||
|  | 		self.image = glumpy.image.Image(I, interpolation="nearest" ,colormap=self.cmap_jet, vmin= 0.0, vmax=255)	 | ||||||
|  | 		C = np.linspace(0,255,256).astype(np.float32) | ||||||
|  | 		C = C.reshape((1,256)) | ||||||
|  | 		self.colorbar = glumpy.image.Image(C, colormap=self.cmap_jet) | ||||||
|  | 		self.values_text = [0,40,80,120,160,200,240] | ||||||
|  | 		self.tick  = [mapValue(i,0,255,0,self._width-10) for i in self.values_text] | ||||||
|  | 
 | ||||||
|  | 		self.updateGL()  | ||||||
|  | 		 | ||||||
|  | 
 | ||||||
|  | 	def materials(self): | ||||||
|  | 
 | ||||||
|  | 		m = 40*np.ones((30,30)).astype(np.float32) | ||||||
|  | 		self.mat = glumpy.image.Image(m, colormap=self.cmap_jet, vmin=0, vmax=255) | ||||||
|  | 
 | ||||||
|  | 	def updateMaterials(self): | ||||||
|  | 
 | ||||||
|  | 		self.mat.draw(x=self._width-100, y=self._height-50, z=0, width= 10, height=10) | ||||||
|  | 		self.qglColor(QColor(0,0,0)) | ||||||
|  | 		self.renderText(self._width-90, 50, "aluminium") | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	def _clear(self): | ||||||
|  | 		self.qglClearColor(QColor(230, 230, 230)) | ||||||
|  | 	 | ||||||
|  | 	def clear(self): | ||||||
|  | 		self._clear() | ||||||
|  | 		GL.glClear(GL.GL_COLOR_BUFFER_BIT) | ||||||
|  | 		 | ||||||
|  | 		 | ||||||
|  | 	def clearUpdate(self): | ||||||
|  | 		self.image = None | ||||||
|  | 		self.updateGL() | ||||||
|  | 	 | ||||||
|  | 	def initializeGL(self): | ||||||
|  | 		self._clear() | ||||||
|  | 		GL.glDisable(GL.GL_BLEND) | ||||||
|  | 		#glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) | ||||||
|  | 		#glEnable(GL_TEXTURE_2D) | ||||||
|  | 		 | ||||||
|  | 	def paintGL(self): | ||||||
|  | 		self.makeCurrent() | ||||||
|  | 		self.OnDraw() | ||||||
|  | 		 | ||||||
|  | 	def setupZoom(self, value): | ||||||
|  | 		self._zoom =  0.3*value/100.0 | ||||||
|  | 		 | ||||||
|  | 	def setZoom(self,value): | ||||||
|  | 		self._zoom =  0.3*value/100.0 | ||||||
|  | 		self.updateGL() | ||||||
|  | 		 | ||||||
|  | 	def getZoom(self): | ||||||
|  | 		return 100*self._zoom/0.3 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	def wheelEvent(self, event): | ||||||
|  | 		numDegrees = event.delta() / 8 | ||||||
|  | 		numSteps = numDegrees / 15.0 | ||||||
|  | 		self.setZoom(numSteps + self.getZoom()) | ||||||
|  | 		self.refreshZoom.zoom(self.getZoom()) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	def drawAxis(self): | ||||||
|  | 
 | ||||||
|  | 		GL.glDisable(GL.GL_TEXTURE_2D) | ||||||
|  | 		GL.glDisable(GL.GL_BLEND) | ||||||
|  | 
 | ||||||
|  | 		GL.glLineWidth(1) | ||||||
|  | 		GL.glColor3f(0.0, 0.0, 0.0) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 		y0  = 30 | ||||||
|  | 		y1  = y0 + 60 | ||||||
|  | 		_x0 = 30 | ||||||
|  | 		_y0 = self._height-y0 | ||||||
|  | 		_x1 = _x0 + 60 | ||||||
|  | 		_y1 = _y0 - 60 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 		GL.glPointSize(7) | ||||||
|  | 		GL.glBegin(GL.GL_POINTS) | ||||||
|  | 		GL.glVertex2f(_x0,_y0) | ||||||
|  | 		GL.glEnd() | ||||||
|  | 
 | ||||||
|  | 		GL.glBegin(GL.GL_LINES) | ||||||
|  | 		GL.glVertex2f(_x0, _y0) | ||||||
|  | 		GL.glVertex2f(_x0, _y1) | ||||||
|  | 		GL.glVertex2f(_x0, _y0) | ||||||
|  | 		GL.glVertex2f(_x1 ,_y0) | ||||||
|  | 		GL.glEnd() | ||||||
|  | 
 | ||||||
|  | 		_w = 5 | ||||||
|  | 		GL.glBegin(GL.GL_TRIANGLES) | ||||||
|  | 		GL.glVertex2f(_x0 +_w, _y1) | ||||||
|  | 		GL.glVertex2f(_x0 -_w, _y1) | ||||||
|  | 		GL.glVertex2f(_x0,_y1 -_w) | ||||||
|  | 		GL.glEnd() | ||||||
|  | 
 | ||||||
|  | 		GL.glBegin(GL.GL_TRIANGLES) | ||||||
|  | 		GL.glVertex2f(_x1, _y0+_w) | ||||||
|  | 		GL.glVertex2f(_x1, _y0-_w) | ||||||
|  | 		GL.glVertex2f(_x1+_w,_y0) | ||||||
|  | 		GL.glEnd() | ||||||
|  | 
 | ||||||
|  | 		GL.glDisable(GL.GL_BLEND) | ||||||
|  | 		GL.glColor3f(0.0, 0.0, 0.0) | ||||||
|  | 		self.renderText(_x1 + 2*_w, y0+_w, "X") | ||||||
|  | 		self.renderText(_x0-_w, y1 + 4*_w, "Y") | ||||||
|  | 
 | ||||||
|  | 		 | ||||||
|  | 		 | ||||||
|  | 	def OnDraw(self): | ||||||
|  | 
 | ||||||
|  | 		self.clear() | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 		if self.image: | ||||||
|  | 			x = self._width/2.0  - self.N*self._zoom/2.0 | ||||||
|  | 			y = self._height/2.0 - self.M*self._zoom/2.0 | ||||||
|  | 			 | ||||||
|  | 			self.image.draw(x=x, y=y,z=0, width= self.N*self._zoom , height= self.M*self._zoom)	 | ||||||
|  | 			self.colorbar.draw(x=0, y=0, z = 0, width=self._width, height=20 ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 			if self._ImageSim: | ||||||
|  | 				self.tick  = [mapValue(i,-self.DB,0,0,self._width-10) for i in self.values_text] | ||||||
|  | 				x0 = self._width/2.0  - self.N*self._zoom*0.1   | ||||||
|  | 				y0 = self._height/2.0 - self.M*self._zoom/2.0 - self.M*self._zoom*0.02  | ||||||
|  | 				self.qglColor(QColor(0,0,0)) | ||||||
|  | 				self.renderText(x0, y0, " time = %.2f %ss"%(self.time, unichr(956))) | ||||||
|  | 				 | ||||||
|  | 			else: | ||||||
|  | 				self.tick  = [mapValue(i,0,255,0,self._width-10) for i in self.values_text] | ||||||
|  | 				 | ||||||
|  | 		 | ||||||
|  | 			self.qglColor(QColor(0,0,0)) | ||||||
|  | 			for i, t in zip(self.values_text,self.tick): | ||||||
|  | 				if self._ImageSim: | ||||||
|  | 					self.renderText(int(t), self._height-20, str(int(i))+" dB") | ||||||
|  | 				else: | ||||||
|  | 					self.renderText(int(t), self._height-20, str(int(i))) | ||||||
|  | 					 | ||||||
|  | 
 | ||||||
|  | 			self.drawAxis() | ||||||
|  | 
 | ||||||
|  | 			if self.EnableTransducers: | ||||||
|  | 				GL.glDisable(GL.GL_TEXTURE_2D) | ||||||
|  | 				GL.glDisable(GL.GL_BLEND) | ||||||
|  | 				self.drawTransducers() | ||||||
|  | 				 | ||||||
|  | 				 | ||||||
|  | 				 | ||||||
|  | 		 | ||||||
|  | 	def setTransducers(self, X,Y): | ||||||
|  | 		self.XL = X | ||||||
|  | 		self.YL = Y | ||||||
|  | 		 | ||||||
|  | 	def drawTransducers(self): | ||||||
|  | 		 | ||||||
|  | 		x = self._width/2.0   - self.N*self._zoom/2.0 + self.XL*self._zoom  | ||||||
|  | 		y = self._height/2.0  - self.M*self._zoom/2.0 + self.YL*self._zoom | ||||||
|  | 		GL.glLineWidth(5); | ||||||
|  | 		GL.glColor3f(0.0, 0.0, 0.0); | ||||||
|  | 		for j in range(np.size(x,1)): | ||||||
|  | 			for i in range(np.size(x,0)-1): | ||||||
|  | 				GL.glBegin(GL.GL_LINES); | ||||||
|  | 				GL.glVertex2f(x[i,j],  y[i,j]) | ||||||
|  | 				GL.glVertex2f(x[i+1,j],y[i+1,j]); | ||||||
|  | 				GL.glEnd(); | ||||||
|  | 				 | ||||||
|  | 		 | ||||||
|  | 		 | ||||||
|  | 	def resizeGL(self, width, height): | ||||||
|  | 		 | ||||||
|  | 		self._width, self._height =	 width, height | ||||||
|  | 		GL.glViewport(0, 0, width, height); | ||||||
|  | 		GL.glMatrixMode(GL.GL_PROJECTION); | ||||||
|  | 		GL.glLoadIdentity(); | ||||||
|  | 		 | ||||||
|  | 		 | ||||||
|  | 		if self._height==0: | ||||||
|  | 			self._height=1; | ||||||
|  | 			 | ||||||
|  | 		if self._width==0: | ||||||
|  | 			self._width=1; | ||||||
|  | 		 | ||||||
|  | 		GL.glOrtho(0, self._width, 0, self._height, -1, 1) | ||||||
|  | 		GL.glMatrixMode(GL.GL_MODELVIEW); | ||||||
|  | 		GL.glLoadIdentity(); | ||||||
|  | 
 | ||||||
|  | 		self.OnDraw() | ||||||
|  | 		 | ||||||
|  | 
 | ||||||
|  | 		 | ||||||
|  | 
 | ||||||
|  | 	def mousePressEvent(self, event): | ||||||
|  | 		self.DragStart      = QPoint(event.pos()) | ||||||
|  | 		 | ||||||
|  | 	def mouseMoveEvent(self, event): | ||||||
|  | 		 | ||||||
|  | 		self.ActualPosition = QPoint(event.pos()) | ||||||
|  | 		if event.buttons() & Qt.LeftButton: | ||||||
|  | 				 | ||||||
|  | 			self.newOffset  = self.Offset | ||||||
|  | 			x  =  self.ActualPosition.x()-self.DragStart.x() | ||||||
|  | 			y  =  self.ActualPosition.y()-self.DragStart.y()   | ||||||
|  | 			self.Offset = QPoint(x,y) | ||||||
|  | 			self._dx = self.Offset.x() | ||||||
|  | 			self._dy = self.Offset.y()  | ||||||
|  | 			 | ||||||
|  | 			self.updateGL() | ||||||
|  | 
 | ||||||
|  | 		 | ||||||
|  | 
 | ||||||
|  | 	 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user