加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
RayGraphWidget.py 20.71 KB
一键复制 编辑 原始数据 按行查看 历史
redfalsh 提交于 2020-06-01 15:34 . 修复pdd步距设置问题
#!/usr/bin/env python
# encoding: utf-8
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from pyqtgraph import GraphicsLayoutWidget
import pyqtgraph.opengl as gl
from pyqtgraph.opengl import GLViewWidget
import pyqtgraph as pg
pg.setConfigOption('background', '#E3E6E3')
pg.setConfigOption('foreground', 'k')
from win32api import GetSystemMetrics
import numpy as np
import re
SIZE_X = 400
SIZE_Y = 400
SIZE_Z = 400
class RayCanvasWidget(GLViewWidget):
def __init__(self):
super(RayCanvasWidget, self).__init__()
# w = GetSystemMetrics (0)
# h = GetSystemMetrics (1)
# self.setMinimumWidth(w/3)
self.opts['distance'] = 40
self.opts['elevation'] = 0
self.opts['azimuth'] = 0
self.gx = gl.GLGridItem()
self.gx.rotate(90, 0, 1, 0)
self.gx.translate(-10, 0, 0)
# self.addItem(self.gx)
self.gy = gl.GLGridItem()
self.gy.rotate(90, 1, 0, 0)
self.gy.translate(0, -10, 0)
# self.addItem(self.gy)
self.gz = gl.GLGridItem()
self.gz.translate(0, 0, -10)
# self.addItem(self.gz)
# set the scale
self.setScale(SIZE_X,SIZE_Y,SIZE_Z)
self.angle = 0
# 参数设置
# self.updateItems()
# 动态移动点
self.points = [[0,0,0]]
self.sp_move = gl.GLScatterPlotItem(pos=np.array(self.points), size=0.4, color=(0.8, 0.7, 0.0, 1), pxMode=False)
self.addItem(self.sp_move)
# 路线移动点
self.sp_road_move = gl.GLScatterPlotItem(pos=np.array(self.points), size=0.4, color=(1.0, 0.0, 0.0, 1), pxMode=False)
self.addItem(self.sp_road_move)
self.timer = QTimer()
self.timer.timeout.connect(self.TimerMove)
self.timer_cnt = 0
self.timer.start(100)
self.updateItems(angle=0,
ssd=-100,
raySize_x=10,
raySize_y=10,
raySizeEdge_x=0,
raySizeEdge_y=0,
deepth=0
)
def setScale(self, size_x, size_y, size_z):
'''设置实际坐标转换opengl坐标系数'''
# axis range ---> x,y,z
self.x_min = -20
self.x_max = 20
self.y_min = -20
self.y_max = 20
self.z_min = -20
self.z_max = 20
# set real range
self.x_range = size_x
self.y_range = size_y
self.z_range = size_z
# get transform scale
self.x_scale = (self.x_max-self.x_min)/self.x_range
self.y_scale = (self.y_max-self.y_min)/self.y_range
self.z_scale = (self.z_max-self.z_min)/self.z_range
def axisToGL(self,x,y,z):
'''按比例返回opengl中xyz坐标'''
x = x*self.x_scale/2
y = y*self.y_scale/2
z = (self.z_range/2-z)*self.z_scale/2
return x,y,z
def drawWaterTank(self):
'''画水箱'''
size = 21
# z = np.array([[0 for i in range(size)] for i in range(size)])
# p1 = gl.GLSurfacePlotItem(z=z, shader='shaded', color=(0.5, 0.5, 1, 0.1))
# p1.translate(-10, -10, -10)
# self.addItem(p1)
# p2 = gl.GLSurfacePlotItem(z=z, shader='shaded', color=(0.5, 0.5, 1, 0.1))
# p2.translate(-10, -10, -10)
# p2.rotate(90, 1, 0, 0)
# self.addItem(p2)
# p3 = gl.GLSurfacePlotItem(z=z, shader='shaded', color=(0.5, 0.5, 1, 1))
# p3.translate(-10, -10, -10)
# p3.rotate(90, 0, 1, 0)
# self.addItem(p3)
# p4 = gl.GLSurfacePlotItem(z=z, shader='shaded', color=(0.5, 0.5, 1, 1))
# p4.translate(-10, -10, 10)
# p4.rotate(90, 1, 0, 0)
# self.addItem(p4)
def drawRayDirection(self):
"""加速器方向绘画"""
clr = pg.glColor(0,0,200)
# 中心点位置
zero_x = -0
zero_y = -0
zero_z = 20
zero = [zero_x,zero_y,zero_z]
self.zero_ray_direction= zero
x = [zero_x+5,zero_y,zero_z]
y = [zero_x,zero_y+5,zero_z]
z = [zero_x,zero_y,zero_z-5]
# X 箭头坐标
line_x = gl.GLLinePlotItem(pos=np.array([zero,x]), color=clr, width=3, antialias=True)
arrow_left = [zero_x+4,zero_y,zero_z-1]
arrow_right = [zero_x+4,zero_y,zero_z+1]
line_x_1 = gl.GLLinePlotItem(pos=np.array([x,arrow_left]), color=clr, width=3, antialias=True)
line_x_2 = gl.GLLinePlotItem(pos=np.array([x,arrow_right]), color=clr, width=3, antialias=True)
self.addItem(line_x)
self.addItem(line_x_1)
self.addItem(line_x_2)
# Y 箭头坐标
line_y = gl.GLLinePlotItem(pos=np.array([zero,y]), color=clr, width=3, antialias=True)
arrow_left = [zero_x,zero_y+4,zero_z-1]
arrow_right = [zero_x,zero_y+4,zero_z+1]
line_y_1 = gl.GLLinePlotItem(pos=np.array([y,arrow_left]), color=clr, width=3, antialias=True)
line_y_2 = gl.GLLinePlotItem(pos=np.array([y,arrow_right]), color=clr, width=3, antialias=True)
self.addItem(line_y)
self.addItem(line_y_1)
self.addItem(line_y_2)
# Z
arrow_left = [zero_x,zero_y-1,zero_z-4]
arrow_right = [zero_x,zero_y+1,zero_z-4]
line_z = gl.GLLinePlotItem(pos=np.array([zero,z]), color=clr, width=3, antialias=True)
line_z_1 = gl.GLLinePlotItem(pos=np.array([z,arrow_left]), color=clr, width=3, antialias=True)
line_z_2 = gl.GLLinePlotItem(pos=np.array([z,arrow_right]), color=clr, width=3, antialias=True)
self.addItem(line_z)
self.addItem(line_z_1)
self.addItem(line_z_2)
def drawBoxDirection(self):
'''水箱方向'''
# draw direction A->B
self.vLine = gl.GLLinePlotItem(pos=np.array([[self.x_min/2,0,self.z_min/2],[self.x_max/2,0,self.z_min/2]]), color=pg.glColor(0,250,255), width=1, antialias=True)
self.addItem(self.vLine)
# draw direction G->T
self.hLine = gl.GLLinePlotItem(pos=np.array([[0,self.y_min/2,self.z_min/2],[0,self.y_max/2,self.z_min/2]]), color=pg.glColor(0,250,255), width=1, antialias=True)
self.addItem(self.hLine)
# draw direction Z
self.zLine = gl.GLLinePlotItem(pos=np.array([[0,0,self.z_min/2],[0,0,self.z_max/2]]), color=pg.glColor(0,250,255), width=1, antialias=True)
self.addItem(self.zLine)
# 中心点位置
zero_x = -10
zero_y = 0
zero_z = 10
zero = [zero_x,zero_y,zero_z]
self.zero_box_direction= zero
x = [zero_x+5,zero_y,zero_z]
y = [zero_x,zero_y+5,zero_z]
z = [zero_x,zero_y,zero_z-5]
clr = pg.glColor(200,0,0)
# X 箭头坐标
x1 = [10,-10,10]
x2 = [-10,-10,10]
arrow_left = [x2[0]+4,x2[1],x2[2]-1]
arrow_right = [x2[0]+4,x2[1],x2[2]+1]
line_x = gl.GLLinePlotItem(pos=np.array([x1,x2]), color=clr, width=1, antialias=True)
line_x_1 = gl.GLLinePlotItem(pos=np.array([x2,arrow_left]), color=clr, width=1, antialias=True)
line_x_2 = gl.GLLinePlotItem(pos=np.array([x2,arrow_right]), color=clr, width=1, antialias=True)
self.addItem(line_x)
self.addItem(line_x_1)
self.addItem(line_x_2)
# Y 箭头坐标
y1 = [-10,-10,10]
y2 = [-10,10,10]
arrow_left = [y2[0],y2[1]-4,y2[2]-1]
arrow_right = [y2[0],y2[1]-4,y2[2]+1]
line_y = gl.GLLinePlotItem(pos=np.array([y1,y2]), color=clr, width=1, antialias=True)
line_y_1 = gl.GLLinePlotItem(pos=np.array([y2,arrow_left]), color=clr, width=1, antialias=True)
line_y_2 = gl.GLLinePlotItem(pos=np.array([y2,arrow_right]), color=clr, width=1, antialias=True)
self.addItem(line_y)
self.addItem(line_y_1)
self.addItem(line_y_2)
# Z
z1 = [-10,10,10]
z2 = [-10,10,-10]
arrow_left = [z2[0],z2[1]-1,z2[2]+4]
arrow_right = [z2[0],z2[1]+1,z2[2]+4]
line_z = gl.GLLinePlotItem(pos=np.array([z1,z2]), color=clr, width=1, antialias=True)
line_z_1 = gl.GLLinePlotItem(pos=np.array([z2,arrow_left]), color=clr, width=1, antialias=True)
line_z_2 = gl.GLLinePlotItem(pos=np.array([z2,arrow_right]), color=clr, width=1, antialias=True)
self.addItem(line_z)
self.addItem(line_z_1)
self.addItem(line_z_2)
def drawXYZ(self):
# line.rotate(90, 0, 1, 0)
pass
def drawRayQuad(self,x1,y1,x2,y2,z):
'''画射野四边形'''
x1,y1,d = self.axisToGL(x1,y1,z)
x2,y2,d = self.axisToGL(x2,y2,z)
axis = [[x1,y1,d],
[x2,y1,d],
[x2,y2,d],
[x1,y2,d],
[x1,y1,d],]
plt = gl.GLLinePlotItem(pos=np.array(axis), color=pg.glColor(255,255,255), width=1, antialias=True)
self.addItem(plt)
def drawRayEdgeQuad(self,x1,y1,x2,y2,z):
'''画射野边缘四边形'''
x1,y1,d = self.axisToGL(x1,y1,z)
x2,y2,d = self.axisToGL(x2,y2,z)
axis = [[x1,y1,d],
[x2,y1,d],
[x2,y2,d],
[x1,y2,d],
[x1,y1,d],]
plt = gl.GLLinePlotItem(pos=np.array(axis), color=pg.glColor(0,150,225), width=1, antialias=True)
self.addItem(plt)
def drawLight(self,x1,y1,x2,y2,z):
'''画光线示意图'''
x1 = x1*(abs(self.z_range)+abs(self.SSD))/(abs(self.SSD)+abs(z))
x2 = x2*(abs(self.z_range)+abs(self.SSD))/(abs(self.SSD)+abs(z))
y1 = y1*(abs(self.z_range)+abs(self.SSD))/(abs(self.SSD)+abs(z))
y2 = y2*(abs(self.z_range)+abs(self.SSD))/(abs(self.SSD)+abs(z))
z = self.z_range
x1,y1,d = self.axisToGL(x1,y1,z)
x2,y2,d = self.axisToGL(x2,y2,z)
x_l,y_l,ssd = self.axisToGL(0,0,self.SSD)
axis = [[x1,y1,d],
[0,0,ssd],
[x2,y1,d],
[0,0,ssd],
[x2,y2,d],
[0,0,ssd],
[x1,y2,d],
[0,0,ssd],
[x1,y1,d],
]
plt = gl.GLLinePlotItem(pos=np.array(axis), color=pg.glColor(255,255,255), width=1, antialias=True)
self.addItem(plt)
axis = [[x1,y1,d],
[x2,y1,d],
[x2,y2,d],
[x1,y2,d],
[x1,y1,d],]
plt = gl.GLLinePlotItem(pos=np.array(axis), color=pg.glColor(150,0,5), width=2, antialias=True)
self.addItem(plt)
def drawLightPoint(self,ssd):
x,y,z = self.axisToGL(0,0,ssd)
sp_light = gl.GLScatterPlotItem(pos=np.array([[0,0,z]]), size=3.0, color=(1.0, 0, 0.0, 1), pxMode=False)
self.addItem(sp_light)
def drawRoad(self,road):
# if self.angle == 45:
# road = [[r[0],r[1],r[2]] for r in road]
# if self.angle == 135:
# road = [[r[1],-r[0],r[2]] for r in road]
# if self.angle == 225:
# road = [[-r[0],-r[1],r[2]] for r in road]
# if self.angle == 315:
# road = [[-r[1],r[0],r[2]] for r in road]
# 下位机更换了x轴走位方向, 将x取反
self.points = [[-r[0],r[1],r[2]] for r in road]
self.addItem(self.sp_move)
self.addItem(self.sp_road_move)
new_road = []
for r in road:
x,y,z = self.axisToGL(-r[0],r[1],r[2])
new_road.append([x,y,z])
sp_road = gl.GLScatterPlotItem(pos=np.array(new_road), size=0.1, color=(0.0, 1.0, 0.0, 1), pxMode=False)
self.addItem(sp_road)
# road_line = gl.GLLinePlotItem(pos=np.array(new_road), color=pg.glColor(250,255,5), width=1, antialias=True)
# road_line = gl.GLScatterPlotItem(pos=np.array([new_road[0],new_road[-1]]), size=3.0, color=(1.0, 0, 0.0, 1), pxMode=False)
# self.addItem(road_line)
def updateItems(self, angle=0, ssd=-100,raySize_x=10,raySize_y=10,raySizeEdge_x=0,raySizeEdge_y=0,deepth=0,road=[[0,0,0]]):
# self.opts['elevation'] = 30
# self.opts['azimuth'] = 90
# angle=kwargs['angle']
# ssd=kwargs['ssd']
# raySize_x=kwargs['raySize_x']
# raySize_y=kwargs['raySize_y']
# raySizeEdge_x=kwargs['raySizeEdge_x']
# raySizeEdge_y=kwargs['raySizeEdge_y']
# deepth=kwargs['deepth']
# road=kwargs['road']
# self.SSD = ssd*10
self.SSD = ssd*2
self.raySize_x = raySize_x*10
self.raySize_y = raySize_y*10
self.raySizeEdge_x = raySize_x*10/2+raySizeEdge_x
self.raySizeEdge_y = raySize_y*10/2+raySizeEdge_y
self.deepth = deepth
self.angle = angle
# 清空重载
self.items = []
self.addItem(self.gx)
# self.addItem(self.gy)
self.addItem(self.gz)
self.drawWaterTank()
self.drawBoxDirection()
# self.drawRayDirection()
self.drawXYZ()
self.drawRayEdgeQuad(-self.raySizeEdge_x,-self.raySizeEdge_y,self.raySizeEdge_x,self.raySizeEdge_y,self.deepth)
self.drawRayQuad(-self.raySize_x/2,-self.raySize_y/2,self.raySize_x/2,self.raySize_y/2,self.deepth)
self.drawLight(-self.raySize_x/2,-self.raySize_y/2,self.raySize_x/2,self.raySize_y/2,self.deepth)
self.drawLightPoint(self.SSD)
self.drawRoad(road)
# 添加移动
# 根据角度选择相应的度数,不管旋转了多少圈,
# 只需取出一圈360的余值进行计算
azimuth = self.opts['azimuth']
azimuth = azimuth%360
err = 0
ag = angle + 25
if azimuth<=ag:
err = ag-azimuth
if ag<azimuth:
err = -(azimuth-ag)
self.opts['azimuth'] += err
elevation = self.opts['elevation']
self.opts['elevation'] -= elevation%360
self.opts['elevation'] += 30
self.update()
def load_config(self, conf):
if conf['type'] == 'OAR':
num = re.compile('^([0-9]+).*$') #regex for num
road = conf['road']
ssd = float(num.match(conf['ssd']).group(1))
raySizeX = float(num.match(conf['ray_size_x']).group(1))
raySizeY = float(num.match(conf['ray_size_y']).group(1))
raySizeEdgeX = float(num.match(conf['ray_size_edge_x']).group(1))
raySizeEdgeY = float(num.match(conf['ray_size_edge_y']).group(1))
deepth = float(num.match(conf['deepth']).group(1))
# angle = float(conf['angle'])
angle = float(conf['angle']) if 'angle' in conf else 0
self.updateItems(angle=angle,ssd=-ssd,raySize_x=raySizeX,raySize_y=raySizeX,raySizeEdge_x=raySizeEdgeX,raySizeEdge_y=raySizeEdgeY,deepth=deepth,road=road)
if conf['type'] == 'PDD':
num = re.compile('^([0-9]+).*$') #regex for num
road = conf['road']
ssd = float(num.match(conf['ssd']).group(1))
raySizeX = float(num.match(conf['ray_size_x']).group(1))
raySizeY = float(num.match(conf['ray_size_y']).group(1))
deepth = float(num.match(conf['deepth']).group(1))
# angle = float(conf['angle'])
angle = float(conf['angle']) if 'angle' in conf else 0
self.updateItems(angle=angle,ssd=-ssd,raySize_x=raySizeX,raySize_y=raySizeX,road=road)
if conf['type'] == 'SCAN':
num = re.compile('^([0-9]+).*$') #regex for num
road = conf['road']
ssd = float(num.match(conf['ssd']).group(1))
raySizeX = float(num.match(conf['ray_size_x']).group(1))
raySizeY = float(num.match(conf['ray_size_y']).group(1))
deepth = float(num.match(conf['deepth']).group(1))
angle = float(conf['angle']) if 'angle' in conf else 0
self.updateItems(angle=angle,ssd=-ssd,raySize_x=raySizeX,raySize_y=raySizeX,deepth=deepth,road=road)
def updatePos(self, x, y, z):
x, y, z = self.axisToGL(-x,y,z)
self.sp_road_move.setData(pos = np.array([[x,y,z]]))
# self.xline.setData(pos = np.array([[x,y,z],[x,self.y_min/2,z]]))
# self.yline.setData(pos=np.array([[x,y,z],[self.x_min/2,y,z]]))
# self.zline.setData(pos=np.array([[x,y,z],[x,y,self.z_min/2]]))
def paintGL(self, *args, **kwds):
GLViewWidget.paintGL(self, *args, **kwds)
textFont = QFont()
textFont.setPixelSize(10)
self.qglColor(Qt.white)
for i in range(self.x_min,self.x_max+1):
if i%4 == 0:
# x axis
self.renderText(i/2, self.y_max/2+2, self.z_min/2, '%.0f'%(-i/self.x_scale), textFont)
# y axis
self.renderText(self.x_max/2+2, i/2, self.z_min/2, '%.0f'%(i/self.y_scale), textFont)
# z axis
self.renderText(self.x_min/2, self.y_max/2+1, i/2, '%.0f'%(self.z_range/2-i/self.z_scale), textFont)
# self.renderText(0, 0, self.z_max/2+5, '扫描矩阵示意图')
self.qglColor(Qt.blue)
self.renderText(self.x_min/2, self.y_max/2, 11, 'd(mm)', textFont)
self.renderText(0, self.y_max/2+3, self.z_min/2, 'x(mm)', textFont)
self.renderText(self.x_max/2+3, 0, self.z_min/2, 'y(mm)', textFont)
self.qglColor(Qt.red)
textFont.setPixelSize(40)
self.renderText(0, -10, 10, 'x', textFont)
self.renderText(-10, 0, 10, 'y', textFont)
self.renderText(-10, 10, 0, 'z', textFont)
# draw direction text
self.qglColor(Qt.yellow)
self.renderText(0, 0, -self.z_min/2, 'O')
if self.angle == 0:
self.renderText(self.x_min/2, 0, self.z_min/2, 'B')
self.renderText(self.x_max/2, 0, self.z_min/2, 'A')
self.renderText(0, self.y_min/2, self.z_min/2, 'G')
self.renderText(0, self.y_max/2, self.z_min/2, 'T')
if self.angle == 90:
self.renderText(self.x_min/2, 0, self.z_min/2, 'T')
self.renderText(self.x_max/2, 0, self.z_min/2, 'G')
self.renderText(0, self.y_min/2, self.z_min/2, 'B')
self.renderText(0, self.y_max/2, self.z_min/2, 'A')
if self.angle == 180:
self.renderText(self.x_min/2, 0, self.z_min/2, 'A')
self.renderText(self.x_max/2, 0, self.z_min/2, 'B')
self.renderText(0, self.y_min/2, self.z_min/2, 'T')
self.renderText(0, self.y_max/2, self.z_min/2, 'G')
if self.angle == 270:
self.renderText(self.x_min/2, 0, self.z_min/2, 'G')
self.renderText(self.x_max/2, 0, self.z_min/2, 'T')
self.renderText(0, self.y_min/2, self.z_min/2, 'A')
self.renderText(0, self.y_max/2, self.z_min/2, 'B')
def updateSurface(self, x, y, z, size):
try:
self.setScale(size*10*2,size*10*2,SIZE_Z)
x = np.array(x)*self.x_scale/2
y = np.array(y)*self.y_scale/2
z = (self.z_range/2-np.array(z))*self.z_scale/2
self.items = []
self.addItem(self.gx)
self.addItem(self.gy)
self.addItem(self.gz)
self.addItem(self.vLine)
self.addItem(self.hLine)
self.addItem(self.sp1)
for i in range(0,len(x)):
pts = [[a,b,c] for a,b,c in zip(x[i],y[i],z[i])]
sp_points = gl.GLScatterPlotItem(pos=np.array(pts), size=3/len(x), color=(0.0, 1.0, 0.0, 0.5), pxMode=False)
self.addItem(sp_points)
plt = gl.GLLinePlotItem(pos=np.array(pts), color=pg.glColor(0,0,255), width=1, antialias=True)
self.addItem(plt)
z = np.array(z).T
for i in range(0,len(x)):
pts = [[b,a,c] for a,b,c in zip(x[i],y[i],z[i])]
plt = gl.GLLinePlotItem(pos=np.array(pts), color=pg.glColor(0,0,255), width=1, antialias=True)
self.sp1.setData(pos = np.array(pts))
self.addItem(plt)
except:
pass
def updateScanRange(self,size,step,direction,deepth):
try:
self.raySize = size
self.scanStep = step
self.scanPoints = []
s = self.raySize*10
res = int(s) % int(self.scanStep)
# 分割x,y
x = np.arange(-s/2,s/2+1,step)
y = np.arange(-s/2,s/2+1,step)
if not res == 0:
x = np.append(x, s/2)
y = np.append(y, s/2)
if direction == 'A->B':
x, y = np.meshgrid(x, y) # x-y 平面的网格
if direction == 'G->T':
y, x = np.meshgrid(x, y) # x-y 平面的网格
z = x*0 + deepth
self.points = [x,y,z]
self.updateSurface(x,y,z,size)
except:
pass
def TimerMove(self):
self.timer_cnt += 1
try:
if self.points:
if self.timer_cnt >= len(self.points):
self.timer_cnt = 0
i = self.timer_cnt
x,y,z = self.axisToGL(self.points[i][0],self.points[i][1],self.points[i][2])
self.sp_move.setData(pos = np.array([[x,y,z]]))
except:
pass
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化