Esempio n. 1
0
class Winform(QWidget):
	def __init__(self,parent=None):
		super(Winform,self).__init__(parent)
		self.setWindowTitle("双缓冲绘图例子") 
		self.pix =  QPixmap()
		self.lastPoint =  QPoint()
		self.endPoint =  QPoint()
		# 辅助画布
		self.tempPix = QPixmap()
		# 标志是否正在绘图
		self.isDrawing = False    
		self.initUi()
		
	def initUi(self):
		#窗口大小设置为600*500
		self.resize(600, 500);   
		# 画布大小为400*400,背景为白色
		self.pix = QPixmap(400, 400);
		self.pix.fill(Qt.white);
         
	def paintEvent(self,event):
		painter = QPainter(self)
		x = self.lastPoint.x()
		y = self.lastPoint.y()
		w = self.endPoint.x() - x
		h = self.endPoint.y() - y
					
		# 如果正在绘图,就在辅助画布上绘制
		if self.isDrawing :			
			# 将以前pix中的内容复制到tempPix中,保证以前的内容不消失
			self.tempPix = self.pix
			pp = QPainter( self.tempPix)
			pp.drawRect(x,y,w,h)
			painter.drawPixmap(0, 0, self.tempPix)
		else :
			pp = QPainter(self.pix )
			pp.drawRect(x, y, w, h)
			painter.drawPixmap(0, 0, self.pix)
		
	def mousePressEvent(self, event) :   
		# 鼠标左键按下   
		if event.button() == Qt.LeftButton :
			self.lastPoint = event.pos()   
			self.endPoint = self.lastPoint
			self.isDrawing = True
	
	def mouseReleaseEvent( self, event):	
		# 鼠标左键释放   
		if event.button() == Qt.LeftButton :
			self.endPoint = event.pos()
			#进行重新绘制
			self.update()
			self.isDrawing = False
Esempio n. 2
0
class Bullet:
	"""Bullet contains:
		1 StartPosition
		2 EndPosition
		3 Color
		4 Text( A String)
		5 Duration
		It uses the "window"  to draw it selft
	"""
	#这个叫做  类的属性  
	Count=0# 通过类名Bullet.bullet访问,就是一个静态变量
	Height=GLOBAL.BULLETFONTSIZE+6 #一个Bullet占用的像素高度
	def __init__(self, Text, Color,Duration):
		Bullet.Count+=1
		#这个里面self给定的内容则只属于当前对象
		self.Text=Text
		self.Color=Color
		self.Duration=Duration*1000 #单位是毫秒,输入的是秒
		self.IsExpired=False

	"""this method must be called when this 
		bullet is ready to shoot at the first time
	"""
	def prepare(self):
		self.elapsedTimer=QElapsedTimer()
		self.elapsedTimer.start() #start time
		self.StartPosition=QPoint(GLOBAL.WINDOWWIDTH+random.randrange(200,500,20),\
			(Bullet.Height+(Bullet.Count%(GLOBAL.WINDOWHEIGHT//Bullet.Height))*Bullet.Height))
		self.EndPosition=QPoint(-2000 ,self.StartPosition.y())
	"""Draw this bullet at position x,y ,use painter
		Returns True indicates this bullet is out of screen
	"""
	def draw(self,painter):
		ratio=self.elapsedTimer.elapsed()/self.Duration
		if(ratio>0.9):
			self.IsExpired=True
		# pos=ratio*self.EndPosition+(1-ratio)*self.StartPosition
		pos=QPoint(ratio*self.EndPosition.x()+(1-ratio)*self.StartPosition.x(),self.StartPosition.y())
		#这里需要插入绘制字体阴影的代码
		#
		# font.setFixedPitch(True)
		# painter.setFont(font)
		painter.save()
		painter.drawText(pos+QPoint(2,2),self.Text)
		painter.setPen(QPen(self.Color))
		painter.drawText(pos,self.Text)
		painter.restore()

	# def __del__(self):
		# Count-=1
		# print ("刚刚自动Delete了一个bullet\n")
    def draw_item(self, face, painter):
        is_draw = True
        if self.is_clipping:
            is_draw = self.sphere.is_face_visible(face)
        if is_draw:
            polygon = QPolygon()
            for index, point_index in enumerate(face):
                p1_x = int(self.sphere.geom.points[face[index-1]][0])
                p1_y = int(self.sphere.geom.points[face[index-1]][1])
                p1_z = int(self.sphere.geom.points[face[index-1]][2])

                p2_x = int(self.sphere.geom.points[point_index][0])
                p2_y = int(self.sphere.geom.points[point_index][1])
                p2_z = int(self.sphere.geom.points[point_index][2])

                if self.sphere.projection_name == "front":
                    # Фронтальная проекция (вид спереди) -> z = 0
                    real_p1 = QPoint(p1_x, p1_y)
                    real_p2 = QPoint(p2_x, p2_y)
                elif self.sphere.projection_name == "horizontal":
                    # Горизонтальная проекция (вид сверху) -> y = 0
                    real_p1 = QPoint(p1_x, p1_z)
                    real_p2 = QPoint(p2_x, p2_z)
                elif self.sphere.projection_name == "profile":
                    # Профильная проекция (вид сбоку) -> x = 0
                    real_p1 = QPoint(p1_y, p1_z)
                    real_p2 = QPoint(p2_y, p2_z)
                else:
                    real_p1 = QPoint(p1_x, p1_y)
                    real_p2 = QPoint(p2_x, p2_y)

                # Точки для проволочного рисования
                real_p1.setX(self.width()/2 + real_p1.x())
                real_p1.setY(self.height()/2 - real_p1.y())
                real_p2.setX(self.width()/2 + real_p2.x())
                real_p2.setY(self.height()/2 - real_p2.y())

                # Полигоны для рисования с цветом
                polygon.append(real_p1)
                polygon.append(real_p2)

                if not self.is_light:
                    painter.drawLine(real_p1, real_p2)

            if self.is_light:

                painter.setBrush(self.sphere.get_face_light(face, self.faces_color))
                painter.drawPolygon(polygon)
class CanvasView(QtCanvasView):
    itemClickedSignal = pyqtSignal(QtCanvasItem)
    itemMovedSignal = pyqtSignal(QtCanvasItem)
    def __init__(self, arg1=None, arg2=None):
        if type(arg1)==QtCanvas:
            super(CanvasView, self).__init__(arg1, arg2)
        else:
            super(CanvasView, self).__init__(arg1)
        self.moving = QtCanvasItem(None)
        self.moving_start = QPoint()

    def contentsMousePressEvent(self, event):
        self.handleMouseClickEvent(event)

    def contentsMouseDoubleClickEvent(self, event):
        self.handleMouseClickEvent(event)

    def handleMouseClickEvent(self, event):
        p = self.inverseWorldMatrix().map(event.pos())
        l = self.canvas().collisions(p)
        self.moving = QtCanvasItem(None)
        if (not l.isEmpty()):
            self.moving = l.first()
        self.moving_start = p
        self.itemClickedSignal.emit(self.moving)

    def contentsMouseMoveEvent(self, event):
        if (self.moving):
            p = self.inverseWorldMatrix().map(event.pos())
            self.moving.moveBy(p.x() - self.moving_start.x(), p.y() - self.moving_start.y())
            self.moving_start = p
            self.canvas().update()
            self.itemMovedSignal.emit(self.moving)
Esempio n. 5
0
def click():
    window_name = get_window_name()
    query_value = get_query_value()
    automation_type = get_query_automation_type()
    widget = find_widget(window_name, query_value, automation_type)

    if widget is None:
        return {}

    if isinstance(widget, QWidget):
        clicker.click_on(widget)
        return get_widget_json(widget)

    if isinstance(widget, QQuickItem):
        pointf = widget.mapToScene(QPointF(0.0, 0.0))
        x = pointf.x()
        y = pointf.y()
        x += qml_method_or_default(widget, "width", 0.0) / 2.0
        y += qml_method_or_default(widget, "height", 0.0) / 2.0
        window_name = get_window_name()
        root_widget = get_root_widget(window_name)
        point = QPoint(x,y)
        quick_widget = root_widget.childAt(point.x(), point.y())
        clicker.click_on(quick_widget, point)
        return get_widget_json(widget)

    return {}
Esempio n. 6
0
    def snapToGrid(self, position):
        #Return position of closest grid point
        gridSizeX = 40
        gridSizeY = 20
        curPos = QPoint(position.x(), position.y())
        gridPos = QPoint(round(curPos.x() / gridSizeX) * gridSizeX, round(curPos.y() / gridSizeY) * gridSizeY)

        return gridPos
Esempio n. 7
0
class Winform(QWidget):
	def __init__(self,parent=None):
		super(Winform,self).__init__(parent)
		self.setWindowTitle("绘制矩形图形例子") 
		self.pix =  QPixmap()
		self.lastPoint =  QPoint()
		self.endPoint =  QPoint()
		self.initUi()
		
	def initUi(self):
		#窗口大小设置为600*500
		self.resize(600, 500)
		# 画布大小为400*400,背景为白色
		self.pix = QPixmap(400, 400)
		self.pix.fill(Qt.white)
         
	def paintEvent(self,event):
		painter = QPainter(self)
		x = self.lastPoint.x()
		y = self.lastPoint.y()
		w = self.endPoint.x() - x
		h = self.endPoint.y() - y

		pp = QPainter(self.pix)
		pp.drawRect(x, y, w, h)
		painter.drawPixmap(0, 0, self.pix)

	def mousePressEvent(self, event) :   
		# 鼠标左键按下  
		if event.button() == Qt.LeftButton :
			self.lastPoint = event.pos()   
			self.endPoint = self.lastPoint
	
	def mouseMoveEvent(self, event):	
		# 鼠标左键按下的同时移动鼠标
		if event.buttons() and Qt.LeftButton :
			self.endPoint = event.pos()
			#进行重新绘制
			self.update()

	def mouseReleaseEvent( self, event):
		# 鼠标左键释放   
		if event.button() == Qt.LeftButton :
			self.endPoint = event.pos()
			#进行重新绘制
			self.update()
Esempio n. 8
0
 def get_linear_gradient(self):
     fontHeight = self.fontMetrics().height()
     startPoint = QPoint(self.rect().x(), self.rect().y() + 0.5 * (self.rect().height() - fontHeight))
     endPoint = QPoint(startPoint.x(), startPoint.y() + fontHeight)
     linear = QLinearGradient(startPoint, endPoint)
     colorCounts = len(self.colors)
     for i in range(colorCounts):
         linear.setColorAt(0.2 + i / colorCounts, self.colors[i])
     return linear
Esempio n. 9
0
    def kineticMove(self, oldx, oldy, newx, newy ):
        """Start a kinetic move from (oldx, oldy) to (newx, newy)"""
        if newx == oldx and newy == oldy:
            return
        
        speed = QPoint(0,0)
        # solve speed*(speed+1)/2 = delta to ensure 1+2+3+...+speed is as close as possible under delta..
        speed.setX((sqrt(1+8*abs(newx-oldx))-1)/2)
        speed.setY((sqrt(1+8*abs(newy-oldy))-1)/2)
        
        # compute the amount of displacement still needed because we're dealing with integer values.
        diff = QPoint(0,0)
        diff.setX((speed.x() * (speed.x() + 1) // 2) - abs(newx - oldx))
        diff.setY((speed.y() * (speed.y() + 1) // 2) - abs(newy - oldy))

        # Since this function is called for exact moves (not free scrolling)
        # limit the kinetic time to 2 seconds, which means 100 ticks, 5050 pixels.
        if speed.y() > 100:
            speed.setY(100)
            diff.setY(-abs(newy-oldy) + 5050)
            
        # Although it is less likely to go beyond that limit for horizontal scrolling,
        # do it for x as well.
        if speed.x() > 100:
            speed.setX(100)
            diff.setX(-abs(newx-oldx) + 5050)
        
        # move left or right, up or down
        if newx > oldx :
            speed.setX(-speed.x())
            diff.setX(-diff.x())
        if newy > oldy :
            speed.setY(-speed.y())
            diff.setY(-diff.y())
        
        # move immediately by the step that cannot be handled by kinetic scrolling.
        # By construction that step is smaller that the initial speed value.
        self.fastScrollBy(diff)
        
        self.kineticStart(speed)
Esempio n. 10
0
File: test.py Progetto: fqez/sandbox
	def wave(self):
			   
#		print(points[0][0] ,'<', points[1][0], 'and', points[0][1], '>', points[1][1])

		t = self.machine.getTransition(self.t_active)
		init = QPoint(t.getOrig()[0], t.getOrig()[1])
		end = QPoint(t.getDest()[0], t.getDest()[1])
		angle = t.getAngle()
		print('processing transition', t.id, t.orig, t.dest)
		while t.isActive():
			self.pts = [[init.x(), init.y()], [end.x(), end.y()]]
			if self.pts[0][0] <= self.pts[1][0] and self.pts[0][1] >= self.pts[1][1]:
				while self.pts[0][0] <= self.pts[1][0] and self.pts[0][1] >= self.pts[1][1]:
					self.sumPoint(angle)
			elif self.pts[0][0] <= self.pts[1][0] and self.pts[0][1] <= self.pts[1][1]:
				while self.pts[0][0] <= self.pts[1][0] and self.pts[0][1] <= self.pts[1][1]:
					self.sumPoint(angle)
			elif self.pts[0][0] >= self.pts[1][0] and self.pts[0][1] >= self.pts[1][1]:
				while self.pts[0][0] >= self.pts[1][0] and self.pts[0][1] >= self.pts[1][1]:
					self.sumPoint(angle)
			elif self.pts[0][0] >= self.pts[1][0] and self.pts[0][1] <= self.pts[1][1]:
				while self.pts[0][0] >= self.pts[1][0] and self.pts[0][1] <= self.pts[1][1]:
					self.sumPoint(angle)
Esempio n. 11
0
File: gui.py Progetto: fqez/sandbox
	def wave(self):
		
		t = self.machine.getActiveTransition()
		if t != None:

			init = QPoint(t.getOrig()[0], t.getOrig()[1])
			end = QPoint(t.getDest()[0], t.getDest()[1])
			angle = t.getAngle()
			#print('processing transition', t.id, t.orig, t.dest)
			while t.isActive():
			#for i in range(3):	#for testing
				self.pts = [[init.x(), init.y()], [end.x(), end.y()]]
				if self.pts[0][0] <= self.pts[1][0] and self.pts[0][1] >= self.pts[1][1]:
					while self.pts[0][0] <= self.pts[1][0] and self.pts[0][1] >= self.pts[1][1]:
						self.sumPoint(angle)
				elif self.pts[0][0] <= self.pts[1][0] and self.pts[0][1] <= self.pts[1][1]:
					while self.pts[0][0] <= self.pts[1][0] and self.pts[0][1] <= self.pts[1][1]:
						self.sumPoint(angle)
				elif self.pts[0][0] >= self.pts[1][0] and self.pts[0][1] >= self.pts[1][1]:
					while self.pts[0][0] >= self.pts[1][0] and self.pts[0][1] >= self.pts[1][1]:
						self.sumPoint(angle)
				elif self.pts[0][0] >= self.pts[1][0] and self.pts[0][1] <= self.pts[1][1]:
					while self.pts[0][0] >= self.pts[1][0] and self.pts[0][1] <= self.pts[1][1]:
						self.sumPoint(angle)
Esempio n. 12
0
 def setOffset(self, offset):
     # Clamp the offset within the offset bounds
     newOffset = QPoint(min(self.mOffsetBounds.right(),
                         max(self.mOffsetBounds.left(), offset.x())),
                             min(self.mOffsetBounds.bottom(),
                                 max(self.mOffsetBounds.top(), offset.y())))
     if (self.mOffset != newOffset):
         xChanged = self.mOffset.x() != newOffset.x()
         yChanged = self.mOffset.y() != newOffset.y()
         self.mOffset = newOffset
         if (xChanged):
             self.offsetXChanged.emit(self.mOffset.x())
         if (yChanged):
             self.offsetYChanged.emit(self.mOffset.y())
         self.offsetChanged.emit(self.mOffset)
         self.update()
Esempio n. 13
0
 def enemyClick(self, enemy):
     # Opens an info screen on the enemy
     if self.parent.gameover == False and enemy.isDead == False:
     
         if self.parent.isTowerSelected == False:
             # self.statusBarMessage("Enemy clicked")
             self.enemyPopUp = QFrame()
             self.enemyPopUp.setGeometry(500, 500, 100, 100)
         
             grid = QGridLayout()
             self.enemyPopUp.setLayout(grid)
         
             enemyStats = QLabel("Enemy Stats")
             name = QLabel("Name: " + str(enemy.name))
             speed = QLabel("Speed: " + str(enemy.speed))
             health = QLabel("Health: {:.0f}".format(enemy.health))
             pixmap = QLabel()
             pixmap.setPixmap(enemy.picture)
         
             vbox = QVBoxLayout()
             vbox.addWidget(enemyStats)
             vbox.addWidget(name)
             vbox.addWidget(speed)
             vbox.addWidget(health)
 
             grid.addLayout(vbox, 0, 0)
         
             vbox2 = QVBoxLayout()
             vbox2.addWidget(pixmap)
             vbox2.addStretch()
             
             doneButton = QPushButton("Done")
             vbox2.addWidget(doneButton)
             grid.addLayout(vbox2, 0, 1)
             
             location = QPoint(QCursor.pos())
             self.enemyPopUp.move(location.x() - 100, location.y())
             self.enemyPopUp.show()
             doneButton.clicked.connect(self.enemyPopUp.hide)
     
     elif self.parent.gameover == True:
         self.statusBarMessage("The game has ended. Stop doing stuff.")
Esempio n. 14
0
    def download(self):
        grab = None
        for x in range(self._tilesRect.width()):
            for y in range(self._tilesRect.height()):
                tp = Point(self._tilesRect.topLeft() + QPoint(x, y))
                if tp not in self._tilePixmaps:
                    grab = QPoint(tp)
                    break

        if grab is None:
            self._url = QUrl()
            return

        path = 'http://tile.openstreetmap.org/%d/%d/%d.png' % (self.zoom, grab.x(), grab.y())
        self._url = QUrl(path)
        request = QNetworkRequest()
        request.setUrl(self._url)
        request.setRawHeader(b'User-Agent', b'Nokia (PyQt) Graphics Dojo 1.0')
        request.setAttribute(QNetworkRequest.User, grab)
        self._manager.get(request)
Esempio n. 15
0
def fillRegion(layer, fillOrigin):
    # Create that region that will hold the fill
    fillRegion = QRegion()
    # Silently quit if parameters are unsatisfactory
    if (not layer.contains(fillOrigin)):
        return fillRegion
    # Cache cell that we will match other cells against
    matchCell = layer.cellAt(fillOrigin)
    # Grab map dimensions for later use.
    layerWidth = layer.width()
    layerHeight = layer.height()
    layerSize = layerWidth * layerHeight
    # Create a queue to hold cells that need filling
    fillPositions = QList()
    fillPositions.append(fillOrigin)
    # Create an array that will store which cells have been processed
    # This is faster than checking if a given cell is in the region/list
    processedCellsVec = QVector()
    for i in range(layerSize):
        processedCellsVec.append(0xff)
    processedCells = processedCellsVec
    # Loop through queued positions and fill them, while at the same time
    # checking adjacent positions to see if they should be added
    while (not fillPositions.empty()):
        currentPoint = fillPositions.takeFirst()
        startOfLine = currentPoint.y() * layerWidth
        # Seek as far left as we can
        left = currentPoint.x()
        while (left > 0 and layer.cellAt(left - 1, currentPoint.y()) == matchCell):
            left -= 1
        # Seek as far right as we can
        right = currentPoint.x()
        while (right + 1 < layerWidth and layer.cellAt(right + 1, currentPoint.y()) == matchCell):
            right += 1
        # Add cells between left and right to the region
        fillRegion += QRegion(left, currentPoint.y(), right - left + 1, 1)
        # Add cell strip to processed cells
        for i in range(startOfLine + left, right + startOfLine, 1):
            processedCells[i] = 1
        # These variables cache whether the last cell was added to the queue
        # or not as an optimization, since adjacent cells on the x axis
        # do not need to be added to the queue.
        lastAboveCell = False
        lastBelowCell = False
        # Loop between left and right and check if cells above or
        # below need to be added to the queue
        for x in range(left, right+1):
            fillPoint = QPoint(x, currentPoint.y())
            # Check cell above
            if (fillPoint.y() > 0):
                aboveCell = QPoint(fillPoint.x(), fillPoint.y() - 1)
                if (not processedCells[aboveCell.y() * layerWidth + aboveCell.x()] and layer.cellAt(aboveCell) == matchCell):

                    # Do not add the above cell to the queue if its
                    # x-adjacent cell was added.
                    if (not lastAboveCell):
                        fillPositions.append(aboveCell)
                    lastAboveCell = True
                else:
                    lastAboveCell = False

                processedCells[aboveCell.y() * layerWidth + aboveCell.x()] = 1

            # Check cell below
            if (fillPoint.y() + 1 < layerHeight):
                belowCell = QPoint(fillPoint.x(), fillPoint.y() + 1)
                if (not processedCells[belowCell.y() * layerWidth + belowCell.x()] and layer.cellAt(belowCell) == matchCell):

                    # Do not add the below cell to the queue if its
                    # x-adjacent cell was added.
                    if (not lastBelowCell):
                        fillPositions.append(belowCell)
                    lastBelowCell = True
                else:
                    lastBelowCell = False

                processedCells[belowCell.y() * layerWidth + belowCell.x()] = 1

    return fillRegion
Esempio n. 16
0
 def get_real_coordinate(self, pos: QtCore.QPoint):
     return round((pos.x() - self.img_bounds[0]) * self.ratio[0]), round(
         (pos.y() - self.img_bounds[1]) * self.ratio[1])
Esempio n. 17
0
class TimeAxis(QWidget):
    STEP_LIST = [
        10000, 5000, 2500, 2000, 1000, 500, 250, 200, 100, 50, 25, 20, 10, 5,
        1, 0.5, 0.2, 0.1, 0.05, 0.02, 0.01
    ]

    DEFAULT_MARGIN_PIXEL = 0
    MAIN_SCALE_MIN_PIXEL = 50

    def __init__(self):
        super(TimeAxis, self).__init__()

        self.__width = 0
        self.__height = 0
        self.__axis_width = 0
        self.__axis_length = 0

        self.__axis_area = QRect(0, 0, 0, 0)
        self.__paint_area = QRect(0, 0, 0, 0)

        self.__axis_mid = 0
        self.__axis_left = 0
        self.__axis_right = 0
        self.__axis_space_w = 30
        self.__axis_align_offset = 0.3

        self.__thread_width = 0
        self.__thread_left_area = QRect(0, 0, 0, 0)
        self.__thread_right_area = QRect(0, 0, 0, 0)

        self.__offset = 0.0
        self.__scroll = 0.0

        self.__scale_per_page = 10
        self.__pixel_per_scale = 0

        self.__paint_since_scale = 0
        self.__paint_until_scale = 0
        self.__paint_start_scale = 0
        self.__paint_start_offset = 0

        self.__l_pressing = False
        self.__l_down_point = None

        # Real time tips

        self.__tip_font = QFont()
        self.__tip_font.setFamily("微软雅黑")
        self.__tip_font.setPointSize(8)

        self.__enable_real_time_tips = True
        self.__mouse_on_index = HistoricalRecord()
        self.__mouse_on_scale_value = 0.0
        self.__mouse_on_coordinate = QPoint(0, 0)

        self.__era = ''
        self.__layout = LAYOUT_HORIZON

        self.__step_selection = 0
        self.__main_step = 0
        self.__sub_step = 0

        self.setMinimumWidth(400)
        self.setMinimumHeight(500)

        self.set_time_range(0, 2000)

        self.setMouseTracking(True)

        self.__history_core = None
        self.__history_editor = None
        self.__history_threads = []
        self.__left_history_threads = []
        self.__right_history_threads = []

    # ----------------------------------------------------- Method -----------------------------------------------------

    def set_era(self, era: str):
        self.__era = era

    def set_offset(self, offset: float):
        if 0.0 <= offset <= 1.0:
            self.__axis_align_offset = offset
        self.repaint()

    def set_horizon(self):
        self.__layout = LAYOUT_HORIZON
        self.repaint()

    def set_vertical(self):
        self.__layout = LAYOUT_VERTICAL
        self.repaint()

    def set_time_range(self, since: float, until: float):
        self.auto_scale(min(since, until), max(since, until))
        self.repaint()

    def set_history_core(self, history: History):
        self.__history_core = history

    def get_history_threads(self, align: int = ALIGN_RIGHT) -> list:
        return self.__left_history_threads if align == ALIGN_LEFT else self.__right_history_threads

    def add_history_thread(self, thread, align: int = ALIGN_RIGHT):
        if thread not in self.__history_threads:
            if align == ALIGN_LEFT:
                self.__left_history_threads.append(thread)
            else:
                self.__right_history_threads.append(thread)
            self.__history_threads.append(thread)
        self.repaint()

    def remove_history_threads(self, thread):
        if thread in self.__history_threads:
            self.__history_threads.remove(thread)
        if thread in self.__left_history_threads:
            self.__left_history_threads.remove(thread)
        if thread in self.__right_history_threads:
            self.__right_history_threads.remove(thread)
        self.repaint()

    def remove_all_history_threads(self):
        self.__history_threads.clear()
        self.__left_history_threads.clear()
        self.__right_history_threads.clear()
        self.repaint()

    def enable_real_time_tips(self, enable: bool):
        self.__enable_real_time_tips = enable

    # --------------------------------------------------- UI Action ----------------------------------------------------

    def mousePressEvent(self, event):
        if event.button() == QtCore.Qt.LeftButton:
            self.__l_pressing = True
            self.__l_down_point = event.pos()

    def mouseReleaseEvent(self, event):
        if event.button() == QtCore.Qt.LeftButton:
            self.__l_pressing = False
            self.__scroll += self.__offset
            self.__offset = 0
            self.repaint()

    def mouseDoubleClickEvent(self, event):
        now_pos = event.pos()
        index = self.index_from_point(now_pos)
        if index is not None:
            self.popup_editor_for_index(index)

    def mouseMoveEvent(self, event):
        now_pos = event.pos()
        if self.__l_pressing and self.__l_down_point is not None:
            if self.__layout == LAYOUT_HORIZON:
                self.__offset = self.__l_down_point.x() - now_pos.x()
            else:
                self.__offset = self.__l_down_point.y() - now_pos.y()
            self.repaint()
        else:
            self.on_pos_updated(now_pos)

    def wheelEvent(self, event):
        angle = event.angleDelta() / 8
        angle_x = angle.x()
        angle_y = angle.y()

        modifiers = QApplication.keyboardModifiers()

        if modifiers == QtCore.Qt.ControlModifier:
            # Get the value before step update
            current_pos = event.pos()
            current_pos_offset = self.calc_point_to_paint_start_offset(
                current_pos)
            current_pos_scale_value = self.pixel_offset_to_scale_value(
                current_pos_offset)

            self.select_step_scale(self.__step_selection +
                                   (1 if angle_y > 0 else -1))

            # Make the value under mouse keep the same place on the screen
            total_pixel_offset = self.__pixel_per_scale * current_pos_scale_value / self.__main_step
            total_pixel_offset -= current_pos_offset
            self.__scroll = total_pixel_offset - self.__offset
        else:
            self.__scroll += (1 if angle_y < 0 else
                              -1) * self.__pixel_per_scale / 4

        self.repaint()

    # ----------------------------------------------------- Action -----------------------------------------------------

    def popup_editor_for_index(self, index: HistoricalRecord):
        if index is None:
            print('None index.')
            return

        # if index.get_focus_label() == 'index':
        #     source = index.source()
        #     if source is None or source == '':
        #         print('Source is empty.')
        #         return
        #     loader = HistoricalRecordLoader()
        #     if not loader.from_source(source):
        #         print('Load source error : ' + source)
        #         return
        #     records = loader.get_loaded_records()
        #     self.update_records(records)
        # else:
        #     # It's a full record
        #     records = [index]

        self.__history_editor = HistoryEditorDialog(editor_agent=self)
        self.__history_editor.get_history_editor().edit_source(
            index.source(), index.uuid())
        self.__history_editor.show_browser(False)
        self.__history_editor.exec()

    # ----------------------------------------------------- Paint ------------------------------------------------------

    def paintEvent(self, event):
        qp = QPainter()
        qp.begin(self)

        self.update_paint_area()
        self.update_pixel_per_scale()
        self.calc_paint_parameters()
        self.calc_paint_layout()

        self.paint_background(qp)

        if self.__layout == LAYOUT_HORIZON:
            self.paint_horizon(qp)
        else:
            self.paint_vertical(qp)
        self.paint_threads(qp)
        self.paint_real_time_tips(qp)

        qp.end()

    def paint_background(self, qp: QPainter):
        qp.setBrush(AXIS_BACKGROUND_COLORS[2])
        qp.drawRect(0, 0, self.__width, self.__height)

    def paint_horizon(self, qp: QPainter):
        pass

    def paint_vertical(self, qp: QPainter):
        qp.drawLine(self.__axis_mid, 0, self.__axis_mid, self.__height)

        main_scale_start = int(self.__axis_mid - 15)
        main_scale_end = int(self.__axis_mid + 15)
        sub_scale_start = int(self.__axis_mid - 5)
        sub_scale_end = int(self.__axis_mid + 5)

        for i in range(0, 12):
            y_main = int(
                self.__pixel_per_scale *
                i) - self.__paint_start_offset + TimeAxis.DEFAULT_MARGIN_PIXEL
            time_main = (self.__paint_start_scale + i) * self.__main_step
            qp.drawLine(main_scale_start, y_main, main_scale_end, y_main)
            qp.drawText(main_scale_end - 100, y_main, str(time_main))
            for j in range(0, 10):
                y_sub = int(y_main + self.__pixel_per_scale * j / 10)
                qp.drawLine(sub_scale_start, y_sub, sub_scale_end, y_sub)

    def paint_threads(self, qp: QPainter):
        for thread in self.__history_threads:
            thread.repaint(qp)

    def paint_real_time_tips(self, qp: QPainter):
        if not self.__enable_real_time_tips or self.__l_pressing:
            return

        qp.drawLine(0, self.__mouse_on_coordinate.y(), self.__width,
                    self.__mouse_on_coordinate.y())
        qp.drawLine(self.__mouse_on_coordinate.x(), 0,
                    self.__mouse_on_coordinate.x(), self.__height)

        tip_text = self.format_real_time_tip()

        fm = QFontMetrics(self.__tip_font)
        text_width = fm.width(tip_text)
        text_height = fm.height()
        tip_area = QRect(self.__mouse_on_coordinate,
                         QSize(text_width, text_height))

        tip_area.setTop(tip_area.top() - fm.height())
        tip_area.setBottom(tip_area.bottom() - fm.height())
        if tip_area.right() > self.__axis_width:
            tip_area.setLeft(tip_area.left() - text_width)
            tip_area.setRight(tip_area.right() - text_width)

        qp.setFont(self.__tip_font)
        qp.setBrush(QColor(36, 169, 225))

        qp.drawRect(tip_area)
        qp.drawText(tip_area, Qt.AlignLeft, tip_text)

    # -------------------------------------------------- Calculation ---------------------------------------------------

    def index_from_point(self, point: QPoint) -> HistoricalRecord:
        for thread in self.__history_threads:
            index = thread.index_from_point(point)
            if index is not None:
                return index
        return None

    def calc_point_to_paint_start_offset(self, point):
        if self.__layout == LAYOUT_HORIZON:
            return point.x() - TimeAxis.DEFAULT_MARGIN_PIXEL
        else:
            return point.y() - TimeAxis.DEFAULT_MARGIN_PIXEL

    def update_paint_area(self):
        wnd_size = self.size()
        self.__width = wnd_size.width()
        self.__height = wnd_size.height()
        self.__paint_area.setRect(0, 0, self.__width, self.__width)

        self.__axis_width = self.__height if self.__layout == LAYOUT_HORIZON else self.__width
        self.__axis_length = self.__width if self.__layout == LAYOUT_HORIZON else self.__height
        self.__axis_length -= self.DEFAULT_MARGIN_PIXEL * 2

    def update_pixel_per_scale(self):
        self.__pixel_per_scale = self.__axis_length / self.__scale_per_page
        self.__pixel_per_scale = max(self.__pixel_per_scale,
                                     TimeAxis.MAIN_SCALE_MIN_PIXEL)

    def calc_paint_parameters(self):
        total_pixel_offset = self.__scroll + self.__offset

        self.__paint_since_scale = float(
            total_pixel_offset) / self.__pixel_per_scale
        self.__paint_until_scale = self.__paint_since_scale + self.__axis_length / self.__pixel_per_scale

        self.__paint_start_scale = math.floor(self.__paint_since_scale)
        self.__paint_start_offset = total_pixel_offset - self.__paint_start_scale * self.__pixel_per_scale

        for thread in self.__history_threads:
            thread.on_paint_scale_range_updated(
                self.__paint_since_scale * self.__main_step,
                self.__paint_until_scale * self.__main_step)

    def calc_paint_layout(self):
        era_text_width = 80
        self.__axis_mid = int(self.__axis_width * self.__axis_align_offset)
        self.__axis_left = int(self.__axis_mid - self.__axis_space_w / 2 -
                               10) - era_text_width
        self.__axis_right = int(self.__axis_mid + self.__axis_space_w / 2 + 10)

        left_thread_count = len(self.__left_history_threads)
        right_thread_count = len(self.__right_history_threads)

        left_thread_width = self.__axis_left / left_thread_count if left_thread_count > 0 else 0
        right_thread_width = (self.__axis_width - self.__axis_right) / right_thread_count \
            if right_thread_count > 0 else 0

        # Vertical -> Horizon : Left rotate

        for i in range(0, left_thread_count):
            thread = self.__left_history_threads[i]
            if self.__layout == LAYOUT_HORIZON:
                # TODO: Can we just rotate the QPaint axis?
                pass
            else:
                top = TimeAxis.DEFAULT_MARGIN_PIXEL
                bottom = self.__axis_length - TimeAxis.DEFAULT_MARGIN_PIXEL
                left = i * left_thread_width
                area = QRect(QPoint(left, top),
                             QPoint(left + left_thread_width, bottom))
                thread.on_paint_canvas_size_update(area)

        for i in range(0, right_thread_count):
            thread = self.__right_history_threads[i]
            if self.__layout == LAYOUT_HORIZON:
                # TODO: Can we just rotate the QPaint axis?
                pass
            else:
                top = TimeAxis.DEFAULT_MARGIN_PIXEL
                bottom = self.__axis_length - TimeAxis.DEFAULT_MARGIN_PIXEL
                left = self.__axis_right + i * right_thread_width
                area = QRect(QPoint(left, top),
                             QPoint(left + right_thread_width, bottom))
                thread.on_paint_canvas_size_update(area)

    # ----------------------------------------------------- Scale ------------------------------------------------------

    def pixel_offset_to_scale_value(self, display_pixel_offset: int) -> float:
        delta_pixel_offset = display_pixel_offset + self.__paint_start_offset - self.DEFAULT_MARGIN_PIXEL
        delta_scale_offset = delta_pixel_offset / self.__pixel_per_scale
        return (self.__paint_start_scale +
                delta_scale_offset) * self.__main_step

    def auto_scale(self, since: float, until: float):
        since_rough = lower_rough(since)
        until_rough = upper_rough(until)
        delta = until_rough - since_rough
        delta_rough = upper_rough(delta)
        step_rough = delta_rough / 10

        step_index = 1
        while step_index < len(TimeAxis.STEP_LIST):
            if TimeAxis.STEP_LIST[step_index] < step_rough:
                break
            step_index += 1
        self.select_step_scale(step_index - 1)

        self.update_pixel_per_scale()
        self.__scroll = since_rough * self.__pixel_per_scale

    def select_step_scale(self, step_index: int):
        self.__step_selection = step_index
        self.__step_selection = max(self.__step_selection, 0)
        self.__step_selection = min(self.__step_selection,
                                    len(TimeAxis.STEP_LIST) - 1)

        self.__main_step = TimeAxis.STEP_LIST[self.__step_selection]
        self.__sub_step = self.__main_step / 10

        # abs_num = abs(num)
        # if abs_num >= 100:
        #     index_10 = math.log(abs_num, 10)
        #     round_index_10 = math.floor(index_10)
        #     scale = math.pow(10, round_index_10)
        #     delta = scale / 10
        # elif 10 < abs_num < 100:
        #     delta = 10
        # elif 1 < abs_num <= 10:
        #     delta = 1
        # else:
        #     if sign > 0:
        #         delta = 1
        #     else:
        #         delta = 0
        # return sign * delta * ratio

    # ------------------------------------------ Art ------------------------------------------

    def format_real_time_tip(self) -> str:
        tip_text = '(' + HistoryTime.standard_time_to_str(
            self.__mouse_on_scale_value) + ')'
        if self.__mouse_on_index is not None:
            since = self.__mouse_on_index.since()
            until = self.__mouse_on_index.until()
            abstract_tags = self.__mouse_on_index.get_tags('abstract')
            abstract = abstract_tags[0] if len(abstract_tags) > 0 else ''
            abstract = abstract.strip()

            if len(abstract) > 0:
                tip_text += ' | '
                tip_text += abstract

            if since == until:
                tip_text += ' : [' + HistoryTime.standard_time_to_str(
                    since) + ']'
            else:
                tip_text += '(' + str(math.floor(self.__mouse_on_scale_value - since + 1)) + \
                            '/' + str(math.floor(until - since)) + ') : ['
                tip_text += HistoryTime.standard_time_to_str(since) + \
                            ' - ' + HistoryTime.standard_time_to_str(until) + ']'
        return tip_text

    # ------------------------------------- Real Time Tips ------------------------------------

    def on_pos_updated(self, pos: QPoint):
        if not self.__enable_real_time_tips:
            return
        if self.__mouse_on_coordinate != pos:
            self.__mouse_on_coordinate = pos
            self.__mouse_on_scale_value = self.pixel_offset_to_scale_value(
                pos.y())
            self.__mouse_on_index = self.index_from_point(pos)
            self.repaint()

    # ------------------------------- HistoryRecordEditor.Agent -------------------------------

    def on_apply(self):
        if self.__history_editor is None:
            print('Unexpected Error: History editor is None.')
            return

        records = self.__history_editor.get_history_editor().get_records()

        if records is None or len(records) == 0:
            return

        indexer = HistoricalRecordIndexer()
        indexer.index_records(records)
        indexes = indexer.get_indexes()

        # TODO: Maybe we should named it as update_*()
        self.__history_core.update_records(records)
        self.__history_core.update_indexes(indexes)

        self.__history_editor.on_apply()
        self.__history_editor.close()

        self.repaint()

    def on_cancel(self):
        if self.__history_editor is not None:
            self.__history_editor.close()
        else:
            print('Unexpected Error: History editor is None.')
Esempio n. 18
0
class MandelbrotWidget(QWidget):
    def __init__(self, parent=None):
        super(MandelbrotWidget, self).__init__(parent)

        self.thread = RenderThread()
        self.pixmap = QPixmap()
        self.pixmapOffset = QPoint()
        self.lastDragPos = QPoint()

        self.centerX = DefaultCenterX
        self.centerY = DefaultCenterY
        self.pixmapScale = DefaultScale
        self.curScale = DefaultScale

        self.thread.renderedImage.connect(self.updatePixmap)

        self.setWindowTitle("Mandelbrot")
        self.setCursor(Qt.CrossCursor)
        self.resize(550, 400)

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.fillRect(self.rect(), Qt.black)

        if self.pixmap.isNull():
            painter.setPen(Qt.white)
            painter.drawText(self.rect(), Qt.AlignCenter,
                    "Rendering initial image, please wait...")
            return

        if self.curScale == self.pixmapScale:
            painter.drawPixmap(self.pixmapOffset, self.pixmap)
        else:
            scaleFactor = self.pixmapScale / self.curScale
            newWidth = int(self.pixmap.width() * scaleFactor)
            newHeight = int(self.pixmap.height() * scaleFactor)
            newX = self.pixmapOffset.x() + (self.pixmap.width() - newWidth) / 2
            newY = self.pixmapOffset.y() + (self.pixmap.height() - newHeight) / 2

            painter.save()
            painter.translate(newX, newY)
            painter.scale(scaleFactor, scaleFactor)
            exposed, _ = painter.matrix().inverted()
            exposed = exposed.mapRect(self.rect()).adjusted(-1, -1, 1, 1)
            painter.drawPixmap(exposed, self.pixmap, exposed)
            painter.restore()

        text = "Use mouse wheel or the '+' and '-' keys to zoom. Press and " \
                "hold left mouse button to scroll."
        metrics = painter.fontMetrics()
        textWidth = metrics.width(text)

        painter.setPen(Qt.NoPen)
        painter.setBrush(QColor(0, 0, 0, 127))
        painter.drawRect((self.width() - textWidth) / 2 - 5, 0, textWidth + 10,
                metrics.lineSpacing() + 5)
        painter.setPen(Qt.white)
        painter.drawText((self.width() - textWidth) / 2,
                metrics.leading() + metrics.ascent(), text)

    def resizeEvent(self, event):
        self.thread.render(self.centerX, self.centerY, self.curScale,
                self.size())

    def keyPressEvent(self, event):
        if event.key() == Qt.Key_Plus:
            self.zoom(ZoomInFactor)
        elif event.key() == Qt.Key_Minus:
            self.zoom(ZoomOutFactor)
        elif event.key() == Qt.Key_Left:
            self.scroll(-ScrollStep, 0)
        elif event.key() == Qt.Key_Right:
            self.scroll(+ScrollStep, 0)
        elif event.key() == Qt.Key_Down:
            self.scroll(0, -ScrollStep)
        elif event.key() == Qt.Key_Up:
            self.scroll(0, +ScrollStep)
        else:
            super(MandelbrotWidget, self).keyPressEvent(event)

    def wheelEvent(self, event):
        numDegrees = event.angleDelta().y() / 8
        numSteps = numDegrees / 15.0
        self.zoom(pow(ZoomInFactor, numSteps))

    def mousePressEvent(self, event):
        if event.buttons() == Qt.LeftButton:
            self.lastDragPos = QPoint(event.pos())

    def mouseMoveEvent(self, event):
        if event.buttons() & Qt.LeftButton:
            self.pixmapOffset += event.pos() - self.lastDragPos
            self.lastDragPos = QPoint(event.pos())
            self.update()

    def mouseReleaseEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.pixmapOffset += event.pos() - self.lastDragPos
            self.lastDragPos = QPoint()

            deltaX = (self.width() - self.pixmap.width()) / 2 - self.pixmapOffset.x()
            deltaY = (self.height() - self.pixmap.height()) / 2 - self.pixmapOffset.y()
            self.scroll(deltaX, deltaY)

    def updatePixmap(self, image, scaleFactor):
        if not self.lastDragPos.isNull():
            return

        self.pixmap = QPixmap.fromImage(image)
        self.pixmapOffset = QPoint()
        self.lastDragPosition = QPoint()
        self.pixmapScale = scaleFactor
        self.update()

    def zoom(self, zoomFactor):
        self.curScale *= zoomFactor
        self.update()
        self.thread.render(self.centerX, self.centerY, self.curScale,
                self.size())

    def scroll(self, deltaX, deltaY):
        self.centerX += deltaX * self.curScale
        self.centerY += deltaY * self.curScale
        self.update()
        self.thread.render(self.centerX, self.centerY, self.curScale,
                self.size())
Esempio n. 19
0
class TileSelectionTool(AbstractTileTool):

    def __init__(self, parent = None):
        super().__init__(self.tr("Rectangular Select"),
                           QIcon(":images/22x22/stock-tool-rect-select.png"),
                           QKeySequence(self.tr("R")),
                           parent)
        self.mSelectionMode = SelectionMode.Replace
        self.mSelecting = False

        self.setTilePositionMethod(TilePositionMethod.BetweenTiles)

        self.mSelectionStart = QPoint()

    def tr(self, sourceText, disambiguation = '', n = -1):
        return QCoreApplication.translate('TileSelectionTool', sourceText, disambiguation, n)

    def mousePressed(self, event):
        button = event.button()
        modifiers = event.modifiers()
        if (button == Qt.LeftButton):
            if (modifiers == Qt.ControlModifier):
                self.mSelectionMode = SelectionMode.Subtract
            elif (modifiers == Qt.ShiftModifier):
                self.mSelectionMode = SelectionMode.Add
            elif (modifiers == (Qt.ControlModifier | Qt.ShiftModifier)):
                self.mSelectionMode = SelectionMode.Intersect
            else:
                self.mSelectionMode = SelectionMode.Replace

            self.mSelecting = True
            self.mSelectionStart = self.tilePosition()
            self.brushItem().setTileRegion(QRegion())

    def mouseReleased(self, event):
        if (event.button() == Qt.LeftButton):
            self.mSelecting = False
            document = self.mapDocument()
            selection = document.selectedArea()
            area = self.selectedArea()
            x = self.mSelectionMode
            if x==SelectionMode.Replace:
                selection = area
            elif x==SelectionMode.Add:
                selection += area
            elif x==SelectionMode.Subtract:
                selection = selection.xored(QRegion(area))
            elif x==SelectionMode.Intersect:
                selection &= area

            if (selection != document.selectedArea()):
                cmd = ChangeSelectedArea(document, selection)
                document.undoStack().push(cmd)

            self.brushItem().setTileRegion(QRegion())
            self.updateStatusInfo()

    def languageChanged(self):
        self.setName(self.tr("Rectangular Select"))
        self.setShortcut(QKeySequence(self.tr("R")))

    def tilePositionChanged(self, tilePos):
        if (self.mSelecting):
            self.brushItem().setTileRegion(self.selectedArea())

    def updateStatusInfo(self):
        if (not self.isBrushVisible() or not self.mSelecting):
            super().updateStatusInfo()
            return

        pos = self.tilePosition()
        area = self.selectedArea()
        self.setStatusInfo(self.tr("%d, %d - Rectangle: (%d x %d)"%((pos.x()), pos.y(), area.width(), area.height())))

    def selectedArea(self):
        tilePos = self.tilePosition()
        pos = QPoint(min(tilePos.x(), self.mSelectionStart.x()), min(tilePos.y(), self.mSelectionStart.y()))
        size = QSize(abs(tilePos.x() - self.mSelectionStart.x()), abs(tilePos.y() - self.mSelectionStart.y()))
        return QRect(pos, size)
Esempio n. 20
0
class HelloGLWidget(QOpenGLWidget):
    """HelloGLWidget(QOpenGLWidget)

    Provides a custom widget to display an OpenGL-rendered Qt logo.
    Various properties and slots are defined so that the user can rotate
    the logo, and signals are defined to enable other components to
    react to changes to its orientation.
    """

    # We define three signals that are used to indicate changes to the
    # rotation of the logo.
    xRotationChanged = pyqtSignal(int)
    yRotationChanged = pyqtSignal(int)
    zRotationChanged = pyqtSignal(int)

    def __init__(self, parent=None):
        super(HelloGLWidget, self).__init__(parent)

        self.object = 0
        self.xRot = 0
        self.yRot = 0
        self.zRot = 0

        self.lastPos = QPoint()

        self.trolltechGreen = QColor.fromCmykF(0.40, 0.0, 1.0, 0.0)
        self.trolltechPurple = QColor.fromCmykF(0.39, 0.39, 0.0, 0.0)

        self.setWindowTitle("Hello GL")

    # The rotation of the logo about the x-axis can be controlled using the
    # xRotation property, defined using the following getter and setter
    # methods.

    def getXRotation(self):
        return self.xRot

    # The setXRotation() setter method is also a slot.
    @pyqtSlot(int)
    def setXRotation(self, angle):
        angle = self.normalizeAngle(angle)
        if angle != self.xRot:
            self.xRot = angle
            self.xRotationChanged.emit(angle)
            self.update()

    xRotation = pyqtProperty(int, getXRotation, setXRotation)

    # The rotation of the logo about the y-axis can be controlled using the
    # yRotation property, defined using the following getter and setter
    # methods.

    def getYRotation(self):
        return self.yRot

    # The setYRotation() setter method is also a slot.
    @pyqtSlot(int)
    def setYRotation(self, angle):
        angle = self.normalizeAngle(angle)
        if angle != self.yRot:
            self.yRot = angle
            self.yRotationChanged.emit(angle)
            self.update()

    yRotation = pyqtProperty(int, getYRotation, setYRotation)

    # The rotation of the logo about the z-axis can be controlled using the
    # zRotation property, defined using the following getter and setter
    # methods.

    def getZRotation(self):
        return self.zRot

    # The setZRotation() setter method is also a slot.
    @pyqtSlot(int)
    def setZRotation(self, angle):
        angle = self.normalizeAngle(angle)
        if angle != self.zRot:
            self.zRot = angle
            self.zRotationChanged.emit(angle)
            self.update()

    zRotation = pyqtProperty(int, getZRotation, setZRotation)

    def minimumSizeHint(self):
        return QSize(50, 50)

    def sizeHint(self):
        return QSize(200, 200)

    def initializeGL(self):
        self.gl = self.context().versionFunctions()
        self.gl.initializeOpenGLFunctions()

        self.setClearColor(self.trolltechPurple.darker())
        self.object = self.makeObject()
        self.gl.glShadeModel(self.gl.GL_SMOOTH)
        self.gl.glEnable(self.gl.GL_DEPTH_TEST)
        self.gl.glEnable(self.gl.GL_CULL_FACE)

    def paintGL(self):
        self.gl.glClear(self.gl.GL_COLOR_BUFFER_BIT | self.gl.GL_DEPTH_BUFFER_BIT)
        self.gl.glLoadIdentity()
        self.gl.glTranslated(0.0, 0.0, -10.0)
        self.gl.glRotated(self.xRot / 16.0, 1.0, 0.0, 0.0)
        self.gl.glRotated(self.yRot / 16.0, 0.0, 1.0, 0.0)
        self.gl.glRotated(self.zRot / 16.0, 0.0, 0.0, 1.0)
        self.gl.glCallList(self.object)

    def resizeGL(self, width, height):
        side = min(width, height)
        self.gl.glViewport((width - side) / 2, (height - side) / 2, side, side)

        self.gl.glMatrixMode(self.gl.GL_PROJECTION)
        self.gl.glLoadIdentity()
        self.gl.glOrtho(-0.5, +0.5, +0.5, -0.5, 4.0, 15.0)
        self.gl.glMatrixMode(self.gl.GL_MODELVIEW)

    def mousePressEvent(self, event):
        self.lastPos = QPoint(event.pos())

    def mouseMoveEvent(self, event):
        dx = event.x() - self.lastPos.x()
        dy = event.y() - self.lastPos.y()

        if event.buttons() & Qt.LeftButton:
            self.setXRotation(self.xRot + 8 * dy)
            self.setYRotation(self.yRot + 8 * dx)
        elif event.buttons() & Qt.RightButton:
            self.setXRotation(self.xRot + 8 * dy)
            self.setZRotation(self.zRot + 8 * dx)

        self.lastPos = QPoint(event.pos())

    def makeObject(self):
        genList = self.gl.glGenLists(1)
        self.gl.glNewList(genList, self.gl.GL_COMPILE)

        self.gl.glBegin(self.gl.GL_QUADS)

        x1 = +0.06
        y1 = -0.14
        x2 = +0.14
        y2 = -0.06
        x3 = +0.08
        y3 = +0.00
        x4 = +0.30
        y4 = +0.22

        self.quad(x1, y1, x2, y2, y2, x2, y1, x1)
        self.quad(x3, y3, x4, y4, y4, x4, y3, x3)

        self.extrude(x1, y1, x2, y2)
        self.extrude(x2, y2, y2, x2)
        self.extrude(y2, x2, y1, x1)
        self.extrude(y1, x1, x1, y1)
        self.extrude(x3, y3, x4, y4)
        self.extrude(x4, y4, y4, x4)
        self.extrude(y4, x4, y3, x3)

        Pi = 3.14159265358979323846
        NumSectors = 200

        for i in range(NumSectors):
            angle1 = (i * 2 * Pi) / NumSectors
            x5 = 0.30 * math.sin(angle1)
            y5 = 0.30 * math.cos(angle1)
            x6 = 0.20 * math.sin(angle1)
            y6 = 0.20 * math.cos(angle1)

            angle2 = ((i + 1) * 2 * Pi) / NumSectors
            x7 = 0.20 * math.sin(angle2)
            y7 = 0.20 * math.cos(angle2)
            x8 = 0.30 * math.sin(angle2)
            y8 = 0.30 * math.cos(angle2)

            self.quad(x5, y5, x6, y6, x7, y7, x8, y8)

            self.extrude(x6, y6, x7, y7)
            self.extrude(x8, y8, x5, y5)

        self.gl.glEnd()
        self.gl.glEndList()

        return genList

    def quad(self, x1, y1, x2, y2, x3, y3, x4, y4):
        self.setColor(self.trolltechGreen)

        self.gl.glVertex3d(x1, y1, -0.05)
        self.gl.glVertex3d(x2, y2, -0.05)
        self.gl.glVertex3d(x3, y3, -0.05)
        self.gl.glVertex3d(x4, y4, -0.05)

        self.gl.glVertex3d(x4, y4, +0.05)
        self.gl.glVertex3d(x3, y3, +0.05)
        self.gl.glVertex3d(x2, y2, +0.05)
        self.gl.glVertex3d(x1, y1, +0.05)

    def extrude(self, x1, y1, x2, y2):
        self.setColor(self.trolltechGreen.darker(250 + int(100 * x1)))

        self.gl.glVertex3d(x1, y1, +0.05)
        self.gl.glVertex3d(x2, y2, +0.05)
        self.gl.glVertex3d(x2, y2, -0.05)
        self.gl.glVertex3d(x1, y1, -0.05)

    def normalizeAngle(self, angle):
        while angle < 0:
            angle += 360 * 16
        while angle > 360 * 16:
            angle -= 360 * 16
        return angle

    def setClearColor(self, c):
        self.gl.glClearColor(c.redF(), c.greenF(), c.blueF(), c.alphaF())

    def setColor(self, c):
        self.gl.glColor4f(c.redF(), c.greenF(), c.blueF(), c.alphaF())
Esempio n. 21
0
class GLWidget(QOpenGLWidget):
    xRotationChanged = pyqtSignal(int)
    yRotationChanged = pyqtSignal(int)
    zRotationChanged = pyqtSignal(int)
    zoomChanged = pyqtSignal(int)

    def __init__(self, parent=None):
        super(GLWidget, self).__init__(parent)

        self.model = None

        self.xRot = 1700
        self.yRot = 2850
        self.zRot = 0

        self.viewX = 0
        self.viewY = 0

        self.lastPos = QPoint()

        self.r_back = self.g_back = self.b_back = 0

        self.plotdata = []
        self.plotlen = 16000

        # Where we are centering.
        self.xcenter = 0.0
        self.ycenter = 0.0
        self.zcenter = 0.0

        # Where the eye is
        self.distance = 10.0

        # Field of view in y direction
        self.fovy = 30.0

        # Position of clipping planes.
        self.near = 0.1
        self.far = 1000.0

        # View settings
        self.perspective = 0
        self.lat = 0
        self.minlat = -90
        self.maxlat = 90

        # does not show HUD by default
        self.hud = Hud()
        # self.hud.show("stuff")
        # add a 100ms timer to poll linuxcnc stats
        self.timer = QTimer()
        self.timer.timeout.connect(self.update)
        self.timer.start(100)

    def getOpenglInfo(self):
        info = """
            Vendor: {0}
            Renderer: {1}
            OpenGL Version: {2}
            Shader Version: {3}
        """.format(
            GL.glGetString(GL.GL_VENDOR),
            GL.glGetString(GL.GL_RENDERER),
            GL.glGetString(GL.GL_VERSION),
            GL.glGetString(GL.GL_SHADING_LANGUAGE_VERSION)
        )

        return info

    def minimumSizeHint(self):
        return QSize(50, 50)

    def sizeHint(self):
        return QSize(400, 400)

    def winfo_width(self):
        return self.geometry().width()

    def winfo_height(self):
        return self.geometry().height()

    def setXRotation(self, angle):
        angle = self.normalizeAngle(angle)
        if angle != self.xRot:
            self.xRot = angle
            self.xRotationChanged.emit(angle)
            self.update()

    def setYRotation(self, angle):
        angle = self.normalizeAngle(angle)
        if angle != self.yRot:
            self.yRot = angle
            self.yRotationChanged.emit(angle)
            self.update()

    def setZRotation(self, angle):
        angle = self.normalizeAngle(angle)
        if angle != self.zRot:
            self.zRot = angle
            self.zRotationChanged.emit(angle)
            self.update()

    def setZoom(self, depth):
        self.distance = depth
        self.update()

    def zoomin(self):
        self.distance = self.distance / 1.1
        if self.distance < self.near:
            self.distance = self.near
        self.update()

    def zoomout(self):
        self.distance = self.distance * 1.1
        if self.distance > self.far:
            self.distance = self.far
        self.update()

    def set_latitudelimits(self, minlat, maxlat):
        """Set the new "latitude" limits for rotations."""

        if maxlat > 180:
            return
        if minlat < -180:
            return
        if maxlat <= minlat:
            return
        self.maxlat = maxlat
        self.minlat = minlat

    def initializeGL(self):
        # basic_lighting
        GL.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, (1, -1, .5, 0))
        GL.glLightfv(GL.GL_LIGHT0, GL.GL_AMBIENT, (.2, .2, .2, 0))
        GL.glLightfv(GL.GL_LIGHT0, GL.GL_DIFFUSE, (.6, .6, .4, 0))
        GL.glLightfv(GL.GL_LIGHT0 + 1, GL.GL_POSITION, (-1, -1, .5, 0))
        GL.glLightfv(GL.GL_LIGHT0 + 1, GL.GL_AMBIENT, (.0, .0, .0, 0))
        GL.glLightfv(GL.GL_LIGHT0 + 1, GL.GL_DIFFUSE, (.0, .0, .4, 0))
        GL.glMaterialfv(GL.GL_FRONT_AND_BACK, GL.GL_AMBIENT_AND_DIFFUSE, (1, 1, 1, 0))
        GL.glDisable(GL.GL_CULL_FACE)
        GL.glEnable(GL.GL_LIGHTING)
        GL.glEnable(GL.GL_LIGHT0)
        GL.glEnable(GL.GL_LIGHT0 + 1)
        GL.glDepthFunc(GL.GL_LESS)
        GL.glEnable(GL.GL_DEPTH_TEST)
        GL.glMatrixMode(GL.GL_MODELVIEW)
        GL.glLoadIdentity()

    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)

        # draw Objects
        GL.glPushMatrix()  # Protect our matrix

        # set view size
        w = self.winfo_width()
        h = self.winfo_height()
        GL.glViewport(0, 0, w, h)

        # Clear the background and depth buffer.
        GL.glClearColor(self.r_back, self.g_back, self.b_back, 0.)
        GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT)

        GL.glMatrixMode(GL.GL_PROJECTION)
        GL.glLoadIdentity()
        GLU.gluPerspective(self.fovy, float(w) / float(h), self.near, self.far)

        if 1:
            # Now translate the scene origin away from the world origin
            GL.glMatrixMode(GL.GL_MODELVIEW)
            mat = GL.glGetDoublev(GL.GL_MODELVIEW_MATRIX)
            GL.glLoadIdentity()
            GL.glTranslatef(-(self.xcenter + self.viewX), -(self.ycenter + self.viewY),
                             -(self.zcenter + self.distance))
            GL.glMultMatrixd(mat)
        else:
            GLU.gluLookAt(self.xcenter, self.ycenter, self.zcenter + self.distance,
                          self.xcenter, self.ycenter, self.zcenter,
                          0., 1., 0.)
            GL.glMatrixMode(GL.GL_MODELVIEW)

        # Call objects redraw method.
        self.drawObjects()
        GL.glFlush()  # Tidy up
        GL.glPopMatrix()  # Restore the matrix

    def drawObjects(self, *args):
        if self.winfo_width() == 1: return
        if self.model is None: return

        self.model.traverse()
        # current coords: world
        # the matrices tool2view, work2view, and world2view
        # transform from tool/work/world coords to viewport coords
        # if we want to draw in tool coords, we need to do
        # "tool -> view -> world" (since the current frame is world)
        # and if we want to draw in work coords, we need
        # "work -> view -> world".  For both, we need to invert
        # the world2view matrix to do the second step
        view2world = invert(self.world2view.t)
        # likewise, for backplot, we want to transform the tooltip
        # position from tool coords (where it is [0,0,0]) to work
        # coords, so we need tool -> view -> work
        # so lets also invert the work2view matrix
        view2work = invert(self.work2view.t)

        # since backplot lines only need vertices, not orientation,
        # and the tooltip is at the origin, getting the tool coords
        # is easy
        tx, ty, tz = self.tool2view.t[3][:3]
        # now we have to transform them to the work frame
        wx = tx * view2work[0][0] + ty * view2work[1][0] + tz * view2work[2][0] + view2work[3][0]
        wy = tx * view2work[0][1] + ty * view2work[1][1] + tz * view2work[2][1] + view2work[3][1]
        wz = tx * view2work[0][2] + ty * view2work[1][2] + tz * view2work[2][2] + view2work[3][2]
        # wx, wy, wz are the values to use for backplot
        # so we save them in a buffer
        if len(self.plotdata) == self.plotlen:
            del self.plotdata[:self.plotlen // 10]
        point = [wx, wy, wz]
        if not self.plotdata or point != self.plotdata[-1]:
            self.plotdata.append(point)

        # now lets draw something in the tool coordinate system
        # GL.glPushMatrix()
        # matrixes take effect in reverse order, so the next
        # two lines do "tool -> view -> world"
        # GL.glMultMatrixd(view2world)
        # GL.glMultMatrixd(self.tool2view.t)

        # do drawing here
        # cylinder normally goes to +Z, we want it down
        # GL.glTranslatef(0,0,-60)
        # GLU.gluCylinder(self.q1, 20, 20, 60, 32, 16)

        # back to world coords
        # GL.glPopMatrix()

        # we can also draw in the work coord system
        GL.glPushMatrix()
        # "work -> view -> world"
        GL.glMultMatrixd(view2world)
        GL.glMultMatrixd(self.work2view.t)
        # now we can draw in work coords, and whatever we draw
        # will move with the work, (if the work is attached to
        # a table or indexer or something that moves with
        # respect to the world

        # just a test object, sitting on the table
        # GLU.gluCylinder(self.q2, 40, 20, 60, 32, 16)

        # draw head up display
        if (hasattr(self.hud, "draw")):
            self.hud.draw()

        # draw backplot
        GL.glDisable(GL.GL_LIGHTING)
        GL.glLineWidth(2)
        GL.glColor3f(1.0, 0.5, 0.5)

        GL.glBegin(GL.GL_LINE_STRIP)
        for p in self.plotdata:
            GL.glVertex3f(*p)
        GL.glEnd()

        GL.glEnable(GL.GL_LIGHTING)
        GL.glColor3f(1, 1, 1)
        GL.glLineWidth(1)
        GL.glDisable(GL.GL_BLEND)
        GL.glDepthFunc(GL.GL_LESS)

        # back to world again
        GL.glPopMatrix()

    def plotclear(self):
        del self.plotdata[:self.plotlen]

    def resizeGL(self, width, height):
        side = min(width, height)
        if side < 0:
            return

        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.glMatrixMode(GL.GL_MODELVIEW)

    def mousePressEvent(self, event):
        self.lastPos = event.pos()

    def mouseMoveEvent(self, event):
        dx = event.x() - self.lastPos.x()
        dy = event.y() - self.lastPos.y()

        if event.buttons() & Qt.LeftButton:
            self.setXRotation(self.xRot + 8 * dy)
            self.setYRotation(self.yRot - 8 * dx)
        elif event.buttons() & Qt.RightButton:
            self.setXRotation(self.xRot + 8 * dy)
            self.setZRotation(self.zRot + 8 * dx)
        else:
            # basic panning
            if dx > 0:
                self.viewX -=2
            elif dx < 0:
                self.viewX +=2
            if dy > 0:
                self.viewY +=2
            elif dy < 0:
                self.viewY -=2

        self.lastPos = event.pos()

    def mouseDoubleClickEvent(self, event):
        if event.button() & Qt.RightButton:
            self.plotclear()

    def wheelEvent(self, event):
        # Use the mouse wheel to zoom in/out
        a = event.angleDelta().y() / 200
        if a < 0:
            self.zoomout()
        else:
            self.zoomin()
        event.accept()

    def normalizeAngle(self, angle):
        while angle < 0:
            angle += 360 * 16
        while angle > 360 * 16:
            angle -= 360 * 16
        return angle
class GLWidget(QGLWidget):
    def __init__(self, parent=None):
        super(GLWidget, self).__init__(QGLFormat(QGL.SampleBuffers), parent)

        midnight = QTime(0, 0, 0)
        random.seed(midnight.secsTo(QTime.currentTime()))

        self.object = 0
        self.xRot = 0
        self.yRot = 0
        self.zRot = 0
        self.image = QImage()
        self.bubbles = []
        self.lastPos = QPoint()

        self.trolltechGreen = QColor.fromCmykF(0.40, 0.0, 1.0, 0.0)
        self.trolltechPurple = QColor.fromCmykF(0.39, 0.39, 0.0, 0.0)

        self.animationTimer = QTimer()
        self.animationTimer.setSingleShot(False)
        self.animationTimer.timeout.connect(self.animate)
        self.animationTimer.start(25)

        self.setAutoFillBackground(False)
        self.setMinimumSize(200, 200)
        self.setWindowTitle("Overpainting a Scene")

    def __del__(self):
        self.makeCurrent()
        glDeleteLists(self.object, 1)

    def setXRotation(self, angle):
        angle = self.normalizeAngle(angle)
        if angle != self.xRot:
            self.xRot = angle

    def setYRotation(self, angle):
        angle = self.normalizeAngle(angle)
        if angle != self.yRot:
            self.yRot = angle

    def setZRotation(self, angle):
        angle = self.normalizeAngle(angle)
        if angle != self.zRot:
            self.zRot = angle

    def initializeGL(self):
        self.object = self.makeObject()

    def mousePressEvent(self, event):
        self.lastPos = event.pos()

    def mouseMoveEvent(self, event):
        dx = event.x() - self.lastPos.x()
        dy = event.y() - self.lastPos.y()

        if event.buttons() & Qt.LeftButton:
            self.setXRotation(self.xRot + 8 * dy)
            self.setYRotation(self.yRot + 8 * dx)
        elif event.buttons() & Qt.RightButton:
            self.setXRotation(self.xRot + 8 * dy)
            self.setZRotation(self.zRot + 8 * dx)

        self.lastPos = event.pos()

    def paintEvent(self, event):
        self.makeCurrent()

        glMatrixMode(GL_MODELVIEW)
        glPushMatrix()

        self.qglClearColor(self.trolltechPurple.darker())
        glShadeModel(GL_SMOOTH)
        glEnable(GL_DEPTH_TEST)
        #glEnable(GL_CULL_FACE)
        glEnable(GL_LIGHTING)
        glEnable(GL_LIGHT0)
        glEnable(GL_MULTISAMPLE)
        lightPosition = (0.5, 5.0, 7.0, 1.0)
        glLightfv(GL_LIGHT0, GL_POSITION, lightPosition)

        self.setupViewport(self.width(), self.height())

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        glLoadIdentity()
        glTranslated(0.0, 0.0, -10.0)
        glRotated(self.xRot / 16.0, 1.0, 0.0, 0.0)
        glRotated(self.yRot / 16.0, 0.0, 1.0, 0.0)
        glRotated(self.zRot / 16.0, 0.0, 0.0, 1.0)
        glCallList(self.object)

        glMatrixMode(GL_MODELVIEW)
        glPopMatrix()

        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing)

        for bubble in self.bubbles:
            if bubble.rect().intersects(QRectF(event.rect())):
                bubble.drawBubble(painter)

        self.drawInstructions(painter)
        painter.end()

    def resizeGL(self, width, height):
        self.setupViewport(width, height)

    def showEvent(self, event):
        self.createBubbles(20 - len(self.bubbles))

    def sizeHint(self):
        return QSize(400, 400)

    def makeObject(self):
        list = glGenLists(1)
        glNewList(list, GL_COMPILE)

        glEnable(GL_NORMALIZE)
        glBegin(GL_QUADS)

        logoDiffuseColor = (self.trolltechGreen.red() / 255.0,
                            self.trolltechGreen.green() / 255.0,
                            self.trolltechGreen.blue() / 255.0, 1.0)
        glMaterialfv(GL_FRONT, GL_DIFFUSE, logoDiffuseColor)

        x1 = +0.06
        y1 = -0.14
        x2 = +0.14
        y2 = -0.06
        x3 = +0.08
        y3 = +0.00
        x4 = +0.30
        y4 = +0.22

        self.quad(x1, y1, x2, y2, y2, x2, y1, x1)
        self.quad(x3, y3, x4, y4, y4, x4, y3, x3)

        self.extrude(x1, y1, x2, y2)
        self.extrude(x2, y2, y2, x2)
        self.extrude(y2, x2, y1, x1)
        self.extrude(y1, x1, x1, y1)
        self.extrude(x3, y3, x4, y4)
        self.extrude(x4, y4, y4, x4)
        self.extrude(y4, x4, y3, x3)

        NumSectors = 200

        for i in range(NumSectors):
            angle1 = (i * 2 * math.pi) / NumSectors
            x5 = 0.30 * math.sin(angle1)
            y5 = 0.30 * math.cos(angle1)
            x6 = 0.20 * math.sin(angle1)
            y6 = 0.20 * math.cos(angle1)

            angle2 = ((i + 1) * 2 * math.pi) / NumSectors
            x7 = 0.20 * math.sin(angle2)
            y7 = 0.20 * math.cos(angle2)
            x8 = 0.30 * math.sin(angle2)
            y8 = 0.30 * math.cos(angle2)

            self.quad(x5, y5, x6, y6, x7, y7, x8, y8)

            self.extrude(x6, y6, x7, y7)
            self.extrude(x8, y8, x5, y5)

        glEnd()

        glEndList()
        return list

    def quad(self, x1, y1, x2, y2, x3, y3, x4, y4):
        glNormal3d(0.0, 0.0, -1.0)
        glVertex3d(x1, y1, -0.05)
        glVertex3d(x2, y2, -0.05)
        glVertex3d(x3, y3, -0.05)
        glVertex3d(x4, y4, -0.05)

        glNormal3d(0.0, 0.0, 1.0)
        glVertex3d(x4, y4, +0.05)
        glVertex3d(x3, y3, +0.05)
        glVertex3d(x2, y2, +0.05)
        glVertex3d(x1, y1, +0.05)

    def extrude(self, x1, y1, x2, y2):
        self.qglColor(self.trolltechGreen.darker(250 + int(100 * x1)))

        glNormal3d((x1 + x2) / 2.0, (y1 + y2) / 2.0, 0.0)
        glVertex3d(x1, y1, +0.05)
        glVertex3d(x2, y2, +0.05)
        glVertex3d(x2, y2, -0.05)
        glVertex3d(x1, y1, -0.05)

    def normalizeAngle(self, angle):
        while angle < 0:
            angle += 360 * 16
        while angle > 360 * 16:
            angle -= 360 * 16
        return angle

    def createBubbles(self, number):
        for i in range(number):
            position = QPointF(self.width() * (0.1 + 0.8 * random.random()),
                               self.height() * (0.1 + 0.8 * random.random()))
            radius = min(self.width(),
                         self.height()) * (0.0125 + 0.0875 * random.random())
            velocity = QPointF(
                self.width() * 0.0125 * (-0.5 + random.random()),
                self.height() * 0.0125 * (-0.5 + random.random()))

            self.bubbles.append(Bubble(position, radius, velocity))

    def animate(self):
        for bubble in self.bubbles:
            bubble.move(self.rect())

        self.update()

    def setupViewport(self, width, height):
        side = min(width, height)
        glViewport((width - side) // 2, (height - side) // 2, side, side)

        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        glOrtho(-0.5, +0.5, +0.5, -0.5, 4.0, 15.0)
        glMatrixMode(GL_MODELVIEW)

    def drawInstructions(self, painter):
        text = "Click and drag with the left mouse button to rotate the Qt " \
                "logo."
        metrics = QFontMetrics(self.font())
        border = max(4, metrics.leading())

        rect = metrics.boundingRect(0, 0,
                                    self.width() - 2 * border,
                                    int(self.height() * 0.125),
                                    Qt.AlignCenter | Qt.TextWordWrap, text)
        painter.setRenderHint(QPainter.TextAntialiasing)
        painter.fillRect(QRect(0, 0, self.width(),
                               rect.height() + 2 * border),
                         QColor(0, 0, 0, 127))
        painter.setPen(Qt.white)
        painter.fillRect(QRect(0, 0, self.width(),
                               rect.height() + 2 * border),
                         QColor(0, 0, 0, 127))
        painter.drawText(
            (self.width() - rect.width()) / 2, border, rect.width(),
            rect.height(), Qt.AlignCenter | Qt.TextWordWrap, text)
class PyQtOpenGL(QOpenGLWidget):
    # rotation signals mouse movement
    x_rotation_changed = pyqtSignal(int)
    y_rotation_changed = pyqtSignal(int)
    z_rotation_changed = pyqtSignal(int)
    
    def __init__(self, parent=None):
        super().__init__(parent)
        self.paint_0 = True
        self.paint_1 = True
        self.paint_2 = True
        self.resize_lines = True    # set orthographic matrix multiplier to large/small
        self.resize_lines = False
        
        self.paint_rotation = True
        self.paint_rotation = False
        self.x_rotation = 0         # rotation variables
        self.y_rotation = 0
        self.z_rotation = 0

        self.last_pos = QPoint()

    def normalize_angle(self, angle):
        while angle < 0:
            angle += 360 * 16
        while angle > 360 * 16:
            angle -= 360 * 16
        return angle
    
    # slots for xyz-rotation 
    def set_x_rotation(self, angle):
        angle = self.normalize_angle(angle)
        if angle != self.x_rotation:
            self.x_rotation = angle
            self.x_rotation_changed.emit(angle)
            self.update()

    def set_y_rotation(self, angle):
        angle = self.normalize_angle(angle)
        if angle != self.y_rotation:
            self.y_rotation = angle
            self.y_rotation_changed.emit(angle)
            self.update()

    def set_z_rotation(self, angle):
        angle = self.normalize_angle(angle)
        if angle != self.z_rotation:
            self.z_rotation = angle
            self.z_rotation_changed.emit(angle)
            self.update()
            
    def initializeGL(self):
        # reimplemented
        glClearColor(0.0, 0.0, 1.0, 0.0)    # blue
        
        glEnable(GL_DEPTH_TEST)
        glEnable(GL_CULL_FACE)
        glShadeModel(GL_SMOOTH)
        glEnable(GL_LIGHTING)
        glEnable(GL_LIGHT0)  
        
        lightPosition = [0, 0, 10, 1.0]  
        glLightfv(GL_LIGHT0, GL_POSITION, lightPosition) 

    def paintGL(self):
        # reimplemented
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        glLoadIdentity()
        glTranslatef(0.0, 0.0, -10.0)
        glRotatef(self.x_rotation / 16.0, 1.0, 0.0, 0.0)
        glRotatef(self.y_rotation / 16.0, 0.0, 1.0, 0.0)
        glRotatef(self.z_rotation / 16.0, 0.0, 0.0, 1.0)
        self.draw()      
   
    def draw(self):
        if self.paint_rotation:
            glColor3f(1.0, 0.0, 0.0)    
            glBegin(GL_QUADS)           # bottom of pyramid
            glNormal3f(0, 0, -1)
            glVertex3f(-1 ,-1, 0)
            glVertex3f(-1 ,1, 0)
            glVertex3f(1, 1, 0)
            glVertex3f(1, -1, 0)
            glEnd()
            
            glColor3f(0.0, 0.0, 0.0)
            glBegin(GL_TRIANGLES)       # four sides of pyramid
            glNormal3f(0, -1, 0.707)
            glVertex3f(-1, -1, 0)
            glVertex3f(1, -1, 0)
            glVertex3f(0, 0, 1.2)
            glEnd()

            glBegin(GL_TRIANGLES)
            glNormal3f(1,0, 0.707)
            glVertex3f(1,-1,0)
            glVertex3f(1,1,0)
            glVertex3f(0,0,1.2)
            glEnd()
            
            glBegin(GL_TRIANGLES)
            glNormal3f(0,1,0.707)
            glVertex3f(1,1,0)
            glVertex3f(-1,1,0)
            glVertex3f(0,0,1.2)
            glEnd()
     
            glBegin(GL_TRIANGLES)
            glNormal3f(-1,0,0.707)
            glVertex3f(-1,1,0)
            glVertex3f(-1,-1,0)
            glVertex3f(0,0,1.2)
            glEnd()   

        # square and lines
        if self.paint_0:       
            glColor3f(1.0, 0.0, 0.0)    # functions expects 3 f(loats); RGB: red
            glRectf(-5, -5, 5, 5)       # draw a filled rectangle with above color, position(x,y) pairs from center of window
  
        if self.paint_1: 
            glColor3f(0.0, 1.0, 0.0)    # set color to RGB: green
            x=10
            y=10
            self.draw_loop(x, y)
         
        if self.paint_2: 
            glColor3f(0.0, 0.0, 0.0)    # set color to RGB: black
            x=5
            y=5
            self.draw_loop(x, y)
        
         
    def resizeGL(self, width, height):
        # reimplemented
        side = min(width, height)
        if side < 0:
            return
  
        glViewport((width - side) // 2, (height - side) // 2, side, side)

        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        
        if self.resize_lines:
            glOrtho(-50, 50, -50, 50, -50.0, 50.0)  # for square and lines; combined with pyramid
        else:
            glOrtho(-2, +2, -2, +2, 1.0, 15.0)      # original pyramid setting
            
        glMatrixMode(GL_MODELVIEW)            
                
                
    def draw_loop(self, x, y, incr=10):
        for _ in range(5):
            self.draw_square_lines(x, y)
            x += incr
            y += incr

    def draw_square_lines(self, x=10, y=10, z=0):
        glBegin(GL_LINES)         # begin to draw a line
        glVertex3f(x, y, z)       # start line relative to center of window
        glVertex3f(x, -y, z)      # draw first line
         
        glVertex3f(x, -y, z)
        glVertex3f(-x, -y, z)
         
        glVertex3f(-x, -y, z)
        glVertex3f(-x, y, z)
         
        glVertex3f(-x, y, z)
        glVertex3f(x, y, z)
        glEnd()      


    def mousePressEvent(self, event):
        # reimplemented
        self.last_pos = event.pos()

    def mouseMoveEvent(self, event):
        # reimplemented
        move_x = event.x() - self.last_pos.x()
        move_y = event.y() - self.last_pos.y()

        if event.buttons() & Qt.LeftButton:                     # left mouse button
            self.set_x_rotation(self.x_rotation + 8 * move_y)
            self.set_y_rotation(self.y_rotation + 8 * move_x)
            
        elif event.buttons() & Qt.RightButton:                  # right mouse button 
            self.set_x_rotation(self.x_rotation + 8 * move_y)
            self.set_z_rotation(self.z_rotation + 8 * move_x)   # spin pyramid around itself

        self.last_pos = event.pos()     
Esempio n. 24
0
class GLWidget(QOpenGLWidget):

    clicked = pyqtSignal()

    PROGRAM_VERTEX_ATTRIBUTE, PROGRAM_TEXCOORD_ATTRIBUTE = range(2)

    vsrc = """
attribute highp vec4 vertex;
attribute mediump vec4 texCoord;
varying mediump vec4 texc;
uniform mediump mat4 matrix;
void main(void)
{
    gl_Position = matrix * vertex;
    texc = texCoord;
}
"""

    fsrc = """
uniform sampler2D texture;
varying mediump vec4 texc;
void main(void)
{
    gl_FragColor = texture2D(texture, texc.st);
}
"""

    coords = (((+1, -1, -1), (-1, -1, -1), (-1, +1, -1), (+1, +1, -1)),
              ((+1, +1, -1), (-1, +1, -1), (-1, +1, +1), (+1, +1, +1)),
              ((+1, -1, +1), (+1, -1, -1), (+1, +1, -1), (+1, +1, +1)),
              ((-1, -1, -1), (-1, -1, +1), (-1, +1, +1),
               (-1, +1, -1)), ((+1, -1, +1), (-1, -1, +1), (-1, -1, -1),
                               (+1, -1, -1)), ((-1, -1, +1), (+1, -1, +1),
                                               (+1, +1, +1), (-1, +1, +1)))

    def __init__(self, parent=None):
        super(GLWidget, self).__init__(parent)

        self.clearColor = QColor(Qt.black)
        self.xRot = 0
        self.yRot = 0
        self.zRot = 0
        self.program = None

        self.lastPos = QPoint()

    def minimumSizeHint(self):
        return QSize(50, 50)

    def sizeHint(self):
        return QSize(200, 200)

    def rotateBy(self, xAngle, yAngle, zAngle):
        self.xRot += xAngle
        self.yRot += yAngle
        self.zRot += zAngle
        self.update()

    def setClearColor(self, color):
        self.clearColor = color
        self.update()

    def initializeGL(self):
        self.gl = self.context().versionFunctions()
        self.gl.initializeOpenGLFunctions()

        self.makeObject()

        self.gl.glEnable(self.gl.GL_DEPTH_TEST)
        self.gl.glEnable(self.gl.GL_CULL_FACE)

        vshader = QOpenGLShader(QOpenGLShader.Vertex, self)
        vshader.compileSourceCode(self.vsrc)

        fshader = QOpenGLShader(QOpenGLShader.Fragment, self)
        fshader.compileSourceCode(self.fsrc)

        self.program = QOpenGLShaderProgram()
        self.program.addShader(vshader)
        self.program.addShader(fshader)
        self.program.bindAttributeLocation('vertex',
                                           self.PROGRAM_VERTEX_ATTRIBUTE)
        self.program.bindAttributeLocation('texCoord',
                                           self.PROGRAM_TEXCOORD_ATTRIBUTE)
        self.program.link()

        self.program.bind()
        self.program.setUniformValue('texture', 0)

        self.program.enableAttributeArray(self.PROGRAM_VERTEX_ATTRIBUTE)
        self.program.enableAttributeArray(self.PROGRAM_TEXCOORD_ATTRIBUTE)
        self.program.setAttributeArray(self.PROGRAM_VERTEX_ATTRIBUTE,
                                       self.vertices)
        self.program.setAttributeArray(self.PROGRAM_TEXCOORD_ATTRIBUTE,
                                       self.texCoords)

    def paintGL(self):
        self.gl.glClearColor(self.clearColor.redF(), self.clearColor.greenF(),
                             self.clearColor.blueF(), self.clearColor.alphaF())
        self.gl.glClear(self.gl.GL_COLOR_BUFFER_BIT
                        | self.gl.GL_DEPTH_BUFFER_BIT)

        m = QMatrix4x4()
        m.ortho(-0.5, 0.5, 0.5, -0.5, 4.0, 15.0)
        m.translate(0.0, 0.0, -10.0)
        m.rotate(self.xRot / 16.0, 1.0, 0.0, 0.0)
        m.rotate(self.yRot / 16.0, 0.0, 1.0, 0.0)
        m.rotate(self.zRot / 16.0, 0.0, 0.0, 1.0)

        self.program.setUniformValue('matrix', m)

        for i, texture in enumerate(self.textures):
            texture.bind()
            self.gl.glDrawArrays(self.gl.GL_TRIANGLE_FAN, i * 4, 4)

    def resizeGL(self, width, height):
        side = min(width, height)
        self.gl.glViewport((width - side) // 2, (height - side) // 2, side,
                           side)

    def mousePressEvent(self, event):
        self.lastPos = event.pos()

    def mouseMoveEvent(self, event):
        dx = event.x() - self.lastPos.x()
        dy = event.y() - self.lastPos.y()

        if event.buttons() & Qt.LeftButton:
            self.rotateBy(8 * dy, 8 * dx, 0)
        elif event.buttons() & Qt.RightButton:
            self.rotateBy(8 * dy, 0, 8 * dx)

        self.lastPos = event.pos()

    def mouseReleaseEvent(self, event):
        self.clicked.emit()

    def makeObject(self):
        self.textures = []
        self.texCoords = []
        self.vertices = []

        root = QFileInfo(__file__).absolutePath()

        for i in range(6):
            self.textures.append(
                QOpenGLTexture(
                    QImage(root + ('/textures/metal%d.png' %
                                   (i + 1))).mirrored()))

            for j in range(4):
                self.texCoords.append(((j == 0 or j == 3), (j == 0 or j == 1)))

                x, y, z = self.coords[i][j]
                self.vertices.append((0.2 * x, 0.2 * y, 0.2 * z))
Esempio n. 25
0
class GLWidget(QtWidgets.QOpenGLWidget):
    xRotationChanged = pyqtSignal(int)
    yRotationChanged = pyqtSignal(int)
    zRotationChanged = pyqtSignal(int)
    orthoChanged = pyqtSignal(float)

    def __init__(self, parent):
        # super(GLWidget, self).__init__(parent)
        self.objects = {
            'box': self.makeBox,
            'sphere': self.makeSphere,
            'pyramid': self.makePyramid,
            'thor': self.makeThor,
            'cylinder': self.makeCylinder
        }

        self.csg_objects = {
            'a_or_b': self.makeAorB,
            'a_and_b': self.makeAandB,
            # 'a_not_b': self.makeAnotB,
            # 'b_not_a': self.makeBnotA
        }

        QtWidgets.QOpenGLWidget.__init__(self, parent)
        # Positioning
        self.xRot = 0
        self.yRot = 0
        self.zRot = 0
        self.orthoSize = 1

        self.invertedWheel = False
        self.mouseWheelSensitivity = 5
        self.rotationSensitivity = 5

        self.GLlighting = False

        self.lastPos = QPoint()

        self.object = None

    def setGLlighting(self, value: bool) -> None:
        self.GLlighting = value
        self.update()

    def setMouseWheelInvertion(self, value: bool) -> None:
        self.invertedWheel = value

    def setMouseWheelSensitivity(self, value: int) -> None:
        self.mouseWheelSensitivity = value

    def setRotationSensitivity(self, value: int) -> None:
        self.rotationSensitivity = value

    def getObjectsNames(self):
        return self.objects.keys()

    def setObject(self, objectName, **kwargs):
        if objectName == 'sphere':
            r = kwargs['r']
            step = kwargs['step']
            self.object = self.objects[objectName](r, step)
        elif objectName == 'thor':
            ir = kwargs['ir']
            step = kwargs['step']
            self.object = self.objects[objectName](ir, step)
        elif objectName == 'cylinder':
            r = kwargs['r']
            h = kwargs['h']
            step = kwargs['step']
            self.object = self.objects[objectName](r, h, step)
        elif objectName == 'csg':
            operation = kwargs['operation']
            self.object = self.csg_objects[operation](self.makeBox(),
                                                      self.makeCylinder(
                                                          1, 0.5, 100))
        else:
            self.object = self.objects[objectName]()
        self.update()

    def makeAorB(self, objA, objB):
        drawAorBList = glGenLists(1)
        glNewList(drawAorBList, GL_COMPILE)
        glCallList(objA)
        glCallList(objB)
        glEndList()
        return drawAorBList

    def makeAandB(self, objA, objB):
        drawAandBList = glGenLists(1)
        glNewList(drawAandBList, GL_COMPILE)
        glEnable(GL_CULL_FACE)
        glEnable(GL_DEPTH_TEST)
        glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE)
        glCullFace(GL_BACK)

        glCallList(objA)

        glDepthMask(GL_FALSE)
        glEnable(GL_STENCIL_TEST)
        glStencilOp(GL_KEEP, GL_KEEP, GL_INCR)
        glStencilFunc(GL_ALWAYS, 0, 0)

        glCallList(objB)

        glStencilOp(GL_KEEP, GL_KEEP, GL_DECR)
        glCullFace(GL_FRONT)

        glCallList(objB)

        glDepthMask(GL_TRUE)
        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE)
        glStencilFunc(GL_NOTEQUAL, 0, 1)
        glDisable(GL_DEPTH_TEST)
        glCullFace(GL_BACK)

        glCallList(objA)

        glDisable(GL_STENCIL_TEST)

        glEndList()
        return drawAandBList

    def makeBox(self):
        drawBoxList = glGenLists(1)
        glNewList(drawBoxList, GL_COMPILE)
        # Front
        glBegin(GL_POLYGON)
        glNormal(0, 0, -1)
        glVertex3f(-0.5, -0.5, -0.5)
        glVertex3f(-0.5, 0.5, -0.5)
        glVertex3f(0.5, 0.5, -0.5)
        glVertex3f(0.5, -0.5, -0.5)
        glEnd()

        # Back
        glBegin(GL_POLYGON)
        glColor3f(1.0, 1.0, 1.0)
        glNormal(0, 0, 1)
        glVertex3f(0.5, -0.5, 0.5)
        glVertex3f(0.5, 0.5, 0.5)
        glVertex3f(-0.5, 0.5, 0.5)
        glVertex3f(-0.5, -0.5, 0.5)
        glEnd()
        #
        # Right
        glBegin(GL_POLYGON)
        glColor3f(1.0, 0.0, 1.0)
        glNormal(1, 0, 0)
        glVertex3f(0.5, -0.5, -0.5)
        glVertex3f(0.5, 0.5, -0.5)
        glVertex3f(0.5, 0.5, 0.5)
        glVertex3f(0.5, -0.5, 0.5)
        glEnd()
        #
        # Left
        glBegin(GL_POLYGON)
        glColor3f(0.0, 1.0, 0.0)
        glNormal(-1, 0, 0)
        glVertex3f(-0.5, -0.5, 0.5)
        glVertex3f(-0.5, 0.5, 0.5)
        glVertex3f(-0.5, 0.5, -0.5)
        glVertex3f(-0.5, -0.5, -0.5)
        glEnd()
        #
        # Top
        glBegin(GL_POLYGON)
        glColor3f(0.0, 0.0, 1.0)
        glNormal(0, 1, 0)
        glVertex3f(0.5, 0.5, 0.5)
        glVertex3f(0.5, 0.5, -0.5)
        glVertex3f(-0.5, 0.5, -0.5)
        glVertex3f(-0.5, 0.5, 0.5)
        glEnd()
        #
        # Bottom
        glBegin(GL_POLYGON)
        glNormal(0, -1, 0)
        glColor3f(1.0, 0.0, 0.0)
        glVertex3f(0.5, -0.5, -0.5)
        glVertex3f(0.5, -0.5, 0.5)
        glVertex3f(-0.5, -0.5, 0.5)
        glVertex3f(-0.5, -0.5, -0.5)
        glEnd()
        glEndList()

        return drawBoxList

    def makeSphere(self, r, step):
        drawSphereList = glGenLists(1)
        glNewList(drawSphereList, GL_COMPILE)
        for i in range(step + 1):
            lat0 = math.pi * (-0.5 + i - 1 / step)
            z0 = math.sin(lat0)
            zr0 = math.cos(lat0)

            lat1 = math.pi * (-0.5 + i / step)
            z1 = math.sin(lat1)
            zr1 = math.cos(lat1)
            glBegin(GL_QUAD_STRIP)
            for j in range(step + 1):
                lng = 2 * math.pi * (j - 1) / step
                x = math.cos(lng)
                y = math.sin(lng)
                glNormal3f(x * zr0, y * zr0, z0)
                glColor3f(i % 2, 1, 0)
                glVertex3f(r * x * zr0, r * y * zr0, r * z0)
                glNormal3f(x * zr1, y * zr1, z1)
                glColor3f(1, j % 2, 0)
                glVertex3f(r * x * zr1, r * y * zr1, r * z1)
            glEnd()
        glEndList()
        return drawSphereList

    def makeThor(self, internal_radius, step):
        drawThorList = glGenLists(1)
        glNewList(drawThorList, GL_COMPILE)
        for i in range(step + 1):
            glBegin(GL_QUAD_STRIP)
            for j in range(step + 1):
                k = 1
                while k >= 0:
                    s = (i + k) % step + 0.5
                    t = j % step
                    radius = 1 - internal_radius
                    x = (1 + radius * math.cos(s * 2 * math.pi / step)
                         ) * math.sin(t * 2 * math.pi / step)
                    y = (1 + radius * math.cos(s * 2 * math.pi / step)
                         ) * math.cos(t * 2 * math.pi / step)
                    z = radius * math.sin(s * 2 * math.pi / step)
                    glNormal(x, y, z)
                    glVertex3f(x, y, z)
                    k -= 1
            glEnd()
        glEndList()
        return drawThorList

    def makePyramid(self):
        drawPyramidList = glGenLists(1)
        glNewList(drawPyramidList, GL_COMPILE)
        # Face 1
        glBegin(GL_POLYGON)
        glColor3f(1.0, 0.0, 1.0)
        glNormal(0, 0.5, 0.5)
        glVertex3f(0.5, 0.5, 0)
        glVertex3f(-0.5, 0.5, 0)
        glVertex3f(0, 0, 0.5)
        glEnd()
        #
        # Face 2
        glBegin(GL_POLYGON)
        glColor3f(1.0, 1.0, 1.0)
        glNormal(-0.5, 0, 0.5)
        glVertex3f(-0.5, 0.5, 0)
        glVertex3f(-0.5, -0.5, 0)
        glVertex3f(0, 0, 0.5)
        glEnd()
        #
        # Face 3
        glBegin(GL_POLYGON)
        glColor3f(0.0, 0.0, 1.0)
        glNormal(0, -0.5, 0.5)
        glVertex3f(-0.5, -0.5, 0)
        glVertex3f(0.5, -0.5, 0)
        glVertex3f(0, 0, 0.5)
        glEnd()
        #
        # Face 4
        glBegin(GL_POLYGON)
        glColor3f(0.0, 0.5, 1.0)
        glNormal(0.5, 0, 0.5)
        glVertex3f(0.5, -0.5, 0)
        glVertex3f(0.5, 0.5, 0)
        glVertex3f(0, 0, 0.5)
        glEnd()
        #
        # Bottom
        glBegin(GL_POLYGON)
        glColor3f(1.0, 0.0, 0.0)
        glNormal(0, 0, -1)
        glVertex3f(-0.5, -0.5, 0.0)
        glVertex3f(0.5, -0.5, 0.0)
        glVertex3f(0.5, 0.5, 0.0)
        glVertex3f(-0.5, 0.5, 0.0)
        glEnd()
        glEndList()
        return drawPyramidList

    def paintGL(self):
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        if self.GLlighting:
            glEnable(GL_LIGHTING)
            glEnable(GL_LIGHT0)
            glEnable(GL_COLOR_MATERIAL)

            glShadeModel(GL_SMOOTH)
            #TODO ShadeModel checkbox

            glMaterialfv(GL_FRONT, GL_SPECULAR, 1, 1, 1, 1)
            glMaterialfv(GL_FRONT, GL_SHININESS, 50)
            glLightfv(GL_LIGHT0, GL_POSITION, 0.5, -1, -0.2, 0)
        else:
            glDisable(GL_LIGHTING)
            glDisable(GL_LIGHT0)
            glDisable(GL_COLOR_MATERIAL)
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        glOrtho(-self.orthoSize, +self.orthoSize, +self.orthoSize,
                -self.orthoSize, 2.0, 15.0)
        glMatrixMode(GL_MODELVIEW)
        glLoadIdentity()
        # glOrtho(-self.orthoSize, +self.orthoSize, +self.orthoSize, -self.orthoSize, 2.0, 15.0)
        # glTranslatef(-2.5, 0.5, -6.0)
        glTranslated(0.0, 0.0, -10.0)
        glColor3f(1.0, 1.5, 0.0)

        glRotated(self.xRot / self.rotationSensitivity, 1.0, 0.0, 0.0)
        glRotated(self.yRot / self.rotationSensitivity, 0.0, 1.0, 0.0)
        glRotated(self.zRot / self.rotationSensitivity, 0.0, 0.0, 1.0)

        glCallList(self.object)

        # glFlush()

    def makeCylinder(self, radius: float, height: float, step: int):
        step = 1 / step
        drawCylinderList = glGenLists(1)
        glNewList(drawCylinderList, GL_COMPILE)
        # Draw the tube
        glColor3f(1.0, 1.0, 1.0)
        glBegin(GL_QUAD_STRIP)
        angle = 0
        while angle < 2 * math.pi:
            x = radius * math.cos(angle)
            y = radius * math.sin(angle)
            glNormal3f(x, y, height // 2)
            glVertex3f(x, y, height // 2)
            glNormal3f(x, y, -height // 2)
            glVertex3f(x, y, -height // 2)
            angle += step
        glVertex3f(radius, 0, height // 2)
        glVertex3f(radius, 0, -height // 2)
        glEnd()
        # Draw the circles
        glColor3f(1, 0.5, 0.5)
        glBegin(GL_POLYGON)
        angle = 0
        while angle < 2 * math.pi:
            x = radius * math.cos(angle)
            y = radius * math.sin(angle)
            glNormal3f(x, y, height // 2)
            glVertex3f(x, y, height // 2)
            angle += step
        glVertex3f(radius, 0, height // 2)
        glEnd()
        glBegin(GL_POLYGON)
        angle = 0
        while angle < 2 * math.pi:
            x = radius * math.cos(angle)
            y = radius * math.sin(angle)
            glNormal3f(x, y, -height // 2)
            glVertex3f(x, y, -height // 2)
            angle += step
        glVertex3f(radius, 0, -height // 2)
        glEnd()
        glEndList()

        return drawCylinderList

    def resetPosition(self) -> None:
        self.xRot = 0
        self.yRot = 0
        self.zRot = 0
        self.orthoSize = 1
        self.update()

    def resizeGL(self, width, height):
        glViewport(0, 0, width, height)
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        glOrtho(-self.orthoSize, +self.orthoSize, +self.orthoSize,
                -self.orthoSize, 2.0, 15.0)
        glMatrixMode(GL_MODELVIEW)

    def initializeGL(self):
        self.setObject('cylinder', r=0.5, h=1, step=100)
        # self.object = self.objects['box']()
        glEnable(GL_DEPTH_TEST)
        glViewport(0, 0, self.width(), self.height())
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        gluPerspective(45.0, self.width() / self.height(), 0.1, 100.0)

    def mouseMoveEvent(self, event):
        dx = event.x() - self.lastPos.x()
        dy = event.y() - self.lastPos.y()

        if event.buttons() & Qt.LeftButton:
            self.setXRotation(self.xRot + dy)
            self.setYRotation(self.yRot + dx)
        elif event.buttons() & Qt.RightButton:
            self.setXRotation(self.xRot + dy)
            self.setZRotation(self.zRot + dx)

    def mousePressEvent(self, event):
        self.lastPos = event.pos()

    def wheelEvent(self, event):
        delta = event.angleDelta().y() / (120 * self.mouseWheelSensitivity)
        delta = -delta if self.invertedWheel else delta
        print(f'Wheel: {delta}')
        self.setOrtho(self.orthoSize + delta)

    def setOrtho(self, value):
        value = self.normalizeOrtho(value)
        if value != self.orthoSize:
            self.orthoSize = value
            # self.orthoChanged.emit(value)
            self.update()
            print(value)

    def normalizeOrtho(self, value):
        if value < 0.05:
            return 0.05
        if value > 2:
            return 2
        return value

    def print_angles(self):
        print(f'X: {self.xRot}\t' f'Y: {self.yRot}\t' f'Z: {self.zRot}\t')

    def setXRotation(self, angle):
        angle = self.normalizeAngle(angle)
        if angle != self.xRot:
            self.xRot = angle
            self.xRotationChanged.emit(angle)
            self.update()
        self.print_angles()

    def setYRotation(self, angle):
        angle = self.normalizeAngle(angle)
        if angle != self.yRot:
            self.yRot = angle
            self.yRotationChanged.emit(angle)
            self.update()
        self.print_angles()

    def setZRotation(self, angle):
        angle = self.normalizeAngle(angle)
        if angle != self.zRot:
            self.zRot = angle
            self.zRotationChanged.emit(angle)
            self.update()
        self.print_angles()

    def normalizeAngle(self, angle):
        while angle < 0:
            angle += 360 * 16
        while angle > 360 * 16:
            angle -= 360 * 16
        return angle
Esempio n. 26
0
class MandelbrotWidget(QWidget):
    def __init__(self, parent=None):
        super(MandelbrotWidget, self).__init__(parent)

        self.thread = RenderThread()
        self.pixmap = QPixmap()
        self.pixmapOffset = QPoint()
        self.lastDragPos = QPoint()

        self.centerX = DefaultCenterX
        self.centerY = DefaultCenterY
        self.pixmapScale = DefaultScale
        self.curScale = DefaultScale

        self.thread.renderedImage.connect(self.updatePixmap)

        self.setWindowTitle("Mandelbrot")
        self.setCursor(Qt.CrossCursor)
        self.resize(550, 400)

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.fillRect(self.rect(), Qt.black)

        if self.pixmap.isNull():
            painter.setPen(Qt.white)
            painter.drawText(
                self.rect(), Qt.AlignCenter, "Rendering initial image, please wait..."
            )
            return

        if self.curScale == self.pixmapScale:
            painter.drawPixmap(self.pixmapOffset, self.pixmap)
        else:
            scaleFactor = self.pixmapScale / self.curScale
            newWidth = int(self.pixmap.width() * scaleFactor)
            newHeight = int(self.pixmap.height() * scaleFactor)
            newX = self.pixmapOffset.x() + (self.pixmap.width() - newWidth) / 2
            newY = self.pixmapOffset.y() + (self.pixmap.height() - newHeight) / 2

            painter.save()
            painter.translate(newX, newY)
            painter.scale(scaleFactor, scaleFactor)
            exposed, _ = painter.matrix().inverted()
            exposed = exposed.mapRect(self.rect()).adjusted(-1, -1, 1, 1)
            painter.drawPixmap(exposed, self.pixmap, exposed)
            painter.restore()

        text = (
            "Use mouse wheel or the '+' and '-' keys to zoom. Press and "
            "hold left mouse button to scroll."
        )
        metrics = painter.fontMetrics()
        textWidth = metrics.width(text)

        painter.setPen(Qt.NoPen)
        painter.setBrush(QColor(0, 0, 0, 127))
        painter.drawRect(
            (self.width() - textWidth) / 2 - 5,
            0,
            textWidth + 10,
            metrics.lineSpacing() + 5,
        )
        painter.setPen(Qt.white)
        painter.drawText(
            (self.width() - textWidth) / 2, metrics.leading() + metrics.ascent(), text
        )

    def resizeEvent(self, event):
        self.thread.render(self.centerX, self.centerY, self.curScale, self.size())

    def keyPressEvent(self, event):
        if event.key() == Qt.Key_Plus:
            self.zoom(ZoomInFactor)
        elif event.key() == Qt.Key_Minus:
            self.zoom(ZoomOutFactor)
        elif event.key() == Qt.Key_Left:
            self.scroll(-ScrollStep, 0)
        elif event.key() == Qt.Key_Right:
            self.scroll(+ScrollStep, 0)
        elif event.key() == Qt.Key_Down:
            self.scroll(0, -ScrollStep)
        elif event.key() == Qt.Key_Up:
            self.scroll(0, +ScrollStep)
        else:
            super(MandelbrotWidget, self).keyPressEvent(event)

    def wheelEvent(self, event):
        numDegrees = event.angleDelta().y() / 8
        numSteps = numDegrees / 15.0
        self.zoom(pow(ZoomInFactor, numSteps))

    def mousePressEvent(self, event):
        if event.buttons() == Qt.LeftButton:
            self.lastDragPos = QPoint(event.pos())

    def mouseMoveEvent(self, event):
        if event.buttons() & Qt.LeftButton:
            self.pixmapOffset += event.pos() - self.lastDragPos
            self.lastDragPos = QPoint(event.pos())
            self.update()

    def mouseReleaseEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.pixmapOffset += event.pos() - self.lastDragPos
            self.lastDragPos = QPoint()

            deltaX = (self.width() - self.pixmap.width()) / 2 - self.pixmapOffset.x()
            deltaY = (self.height() - self.pixmap.height()) / 2 - self.pixmapOffset.y()
            self.scroll(deltaX, deltaY)

    def updatePixmap(self, image, scaleFactor):
        if not self.lastDragPos.isNull():
            return

        self.pixmap = QPixmap.fromImage(image)
        self.pixmapOffset = QPoint()
        self.lastDragPosition = QPoint()
        self.pixmapScale = scaleFactor
        self.update()

    def zoom(self, zoomFactor):
        self.curScale *= zoomFactor
        self.update()
        self.thread.render(self.centerX, self.centerY, self.curScale, self.size())

    def scroll(self, deltaX, deltaY):
        self.centerX += deltaX * self.curScale
        self.centerY += deltaY * self.curScale
        self.update()
        self.thread.render(self.centerX, self.centerY, self.curScale, self.size())
Esempio n. 27
0
 def is_pos_in_separea(self, pos: QPoint):
     if self.scene_type == 0:
         return False
     padding = constants.SEPARATION_PADDING * self.view_rect().height()
     return self.y_sep - padding <= pos.y() <= self.y_sep + padding
Esempio n. 28
0
class CorvusGL3DWidget(QOpenGLWidget):
    xRotationChanged = pyqtSignal(int)
    yRotationChanged = pyqtSignal(int)
    zRotationChanged = pyqtSignal(int)

    def __init__(self, parent=None):
        super(CorvusGL3DWidget, self).__init__(parent)

        self.object = 0
        self.xRot = 0
        self.yRot = 0
        self.zRot = 0
        self.points = []

        self.lastPos = QPoint()

        self.black = QColor.fromRgb(0.0,0.0,0.0)
    
    def minimumSizeHint(self):
        width = 50
        height = 50
        return QSize(width, height)

    def sizeHint(self):
        width = 500
        height = 500
        return QSize(width, height)


    def setXRotation(self, angle):
        angle = self.normalizeAngle(angle)
        if angle != self.xRot:
            self.xRot = angle
            self.xRotationChanged.emit(angle)
            self.update()

    def setYRotation(self, angle):
        angle = self.normalizeAngle(angle)
        if angle != self.yRot:
            self.yRot = angle
            self.yRotationChanged.emit(angle)
            self.update()

    def setZRotation(self, angle):
        angle = self.normalizeAngle(angle)
        if angle != self.zRot:
            self.zRot = angle
            self.zRotationChanged.emit(angle)
            self.update()

    def initializeGL(self):
        self.setClearColor(self.black.darker())
        self.object = self.makeObject()
        gl.glShadeModel(gl.GL_FLAT)
        gl.glEnable(gl.GL_DEPTH_TEST)
        gl.glEnable(gl.GL_CULL_FACE)
    
    def updateObject(self):
        self.setClearColor(self.black.darker())
        self.object = self.makeObject()
        self.repaint()
    
    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.glCallList(self.object)

    def resizeGL(self, width, height):
        side = min(width, height)
        if side < 0:
            return

        gl.glViewport((width - side) // 2, (height - side) // 2, side, side)

        gl.glMatrixMode(gl.GL_PROJECTION)
        gl.glLoadIdentity()
        gl.glOrtho(-1.0, +1.0, +1.0, -1.0, 4.0, 15.0)
        gl.glMatrixMode(gl.GL_MODELVIEW)

    def mousePressEvent(self, event):
        self.lastPos = event.pos()

    def mouseMoveEvent(self, event):
        dx = event.x() - self.lastPos.x()
        dy = event.y() - self.lastPos.y()

        if event.buttons() & Qt.LeftButton:
            self.setXRotation(self.xRot + 8 * -dy)
            self.setYRotation(self.yRot + 8 * dx)
        elif event.buttons() & Qt.RightButton:
            self.setXRotation(self.xRot + 8 * -dy)
            self.setZRotation(self.zRot + 8 * -dx)

        self.lastPos = event.pos()

    def makeObject(self):
        genList = gl.glGenLists(1)
        gl.glNewList(genList, gl.GL_COMPILE)

        gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA)
        gl.glEnable(gl.GL_BLEND )
        
        gl.glBegin(gl.GL_POINTS)
        
        red = 147.5 / 255.0
        green = 167.1 / 255.0
        blue = 186.2 / 255.0

        for p in self.points:
            x = p[0]
            y = p[1]
            z = p[2]
            alpha =  pow((1.0 - (sqrt(pow(x,2) + pow(y,2) + pow(z,2)) / sqrt(3.0))), 4)
            self.setColor(red, green, blue, alpha)
            gl.glVertex3d(x,y,z)

        gl.glEnd()
        gl.glEndList()

        return genList


    def normalizeAngle(self, angle):
        while angle < 0:
            angle += 360 * 16
        while angle > 360 * 16:
            angle -= 360 * 16
        return angle

    def setClearColor(self, c):
        gl.glClearColor(c.redF(), c.greenF(), c.blueF(), c.alphaF())

    def setColor(self, red, green, blue, alpha):
        gl.glColor4f(red, green, blue, alpha)
Esempio n. 29
0
def float_horizon(scene_width, scene_hight, x_min, x_max, x_step, z_min, z_max,
                  z_step, tx, ty, tz, func, image):

    # инициализация массивов горизонтов
    top = {x: 0 for x in range(1, int(scene_width) + 1)}
    bottom = {x: scene_hight for x in range(1, int(scene_width) + 1)}

    z = z_max

    # duyet theo chiều từ gần ra xa
    while z >= z_min:
        #print("z = ", z)
        # mặt phẳng toạ độ Z
        x = x_min
        y = func(x, z)
        # phép quay theo X, Y, Z
        x, y, z_buf = tranform(x, y, z, tx, ty, tz)

        # Обрабатываем левое ребро(смотрим предыдущее с текущим)
        #если точка является первой точкой на первой кривой
        if fabs(z - z_max) < eps:
            P = QPoint(x, y)
        else:
            top, bottom = add_line(P.x(), P.y(), x, y, top, bottom, image)
            P = QPoint(x, y)

        # điểm bắt đầu trong mặt phẳng z = const
        x = x_min
        while x <= x_max:
            #print("\t x = ", x)
            # xác định điểm tiếp theo
            y = func(x, z)
            x_curr, y_curr, z_curr = tranform(x, y, z, tx, ty, tz)
            p_curr = QPoint(x_curr, y_curr)
            isVis_curr = isVisable(p_curr, top, bottom)

            if fabs(x - x_min) > eps:
                isVis_curr = isVisable(p_curr, top, bottom)
                if (isVis_curr * isVis_prev == 0 and isVis_curr + isVis_prev):
                    if (isVis_curr + isVis_prev == 1):
                        try:
                            if (p_prev.x() == p_curr.x()):

                                I = QPoint(p_prev.x(),
                                           min(p_curr.y(), p_prev.y()))
                                top[I.x()] = I.y()
                                print("check", p_prev, p_curr, I, top[I.x()],
                                      isVis_curr, isVis_prev)
                            else:
                                I = intersection(p_prev, p_curr,
                                                 top[p_prev.x()],
                                                 top[p_curr.x()])
                        except:
                            print("err")
                    else:
                        if (p_prev.x() == p_curr.x()):
                            I = QPoint(p_prev.x(), max(p_curr.y(), p_prev.y()))
                            bottom[I.x()] = I.y()
                        else:
                            y1 = bottom[p_prev.x()]
                            y2 = bottom[p_curr.x()]
                            I = intersection(p_prev, p_curr, y1, y2)

                    if (isVis_curr == 0):
                        top, bottom = add_line(p_prev.x(), p_prev.y(), I.x(),
                                               I.y(), top, bottom, image)
                        if (p_prev.x() == p_curr.x()):
                            print('----', top[p_prev.x()], bottom[p_prev.x()])
                    else:
                        top, bottom = add_line(I.x(), I.y(), p_curr.x(),
                                               p_curr.y(), top, bottom, image)
                elif isVis_curr * isVis_prev != 0:
                    top, bottom = add_line(p_prev.x(), p_prev.y(), p_curr.x(),
                                           p_curr.y(), top, bottom, image)
            p_prev = p_curr
            isVis_prev = isVis_curr + 0
            x += x_step

        # Обрабатываем правое ребро(смотрим текущее со следующим)
        if fabs(z - z_max) < eps:
            Q = p_curr
        else:
            top, bottom = add_line(Q.x(), Q.y(), p_curr.x(), p_curr.y(), top,
                                   bottom, image)
            Q = p_curr
        z -= z_step

    return image
Esempio n. 30
0
 def mouseMoveEvent(self, event):
     """if old_pos exists moves the frame"""
     if (self.old_pos):
         delta = QPoint(event.globalPos() - self.old_pos)
         self.move(self.x() + delta.x(), self.y() + delta.y())
         self.old_pos = event.globalPos()
Esempio n. 31
0
class Overlay(QWidget):

    def __init__(self, parent, binpath):
        super().__init__(parent)
        sizePolicy = QSizePolicy()
        sizePolicy.setHorizontalPolicy(QSizePolicy.Maximum)
        sizePolicy.setVerticalPolicy(QSizePolicy.Maximum)
        #self.setSizePolicy(sizePolicy)
        self.setMouseTracking(True)

        self.on_selection = False
        self.selected = False
        self.c = Communicate()

        self.start_position = QPoint(0,0)
        self.last_position = QPoint(0,0)

        image = (
            b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
            b"\x00\x00\xFF\xFF\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00"
            b"\x00\x00\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\x00\x00"
            b"\x00\x00\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\x00\x00"
            b"\x00\x00\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\x00\x00"
            b"\x00\x00\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\x00\x00"
            b"\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\xFF\xFF\x00\x00"
            b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
        im = QImage(image, 8,8, QImage.Format_RGB16)
        im = im.scaled(64,64)
        self.crop = QPixmap()
        self.crop.convertFromImage(im)

    def insideSelection(self, point):
        width = self.last_position.x() - self.start_position.x()
        height = self.last_position.y() - self.start_position.y()

        return (    point.x() > self.start_position.x() and point.x() < self.start_position.x() + width and
                    point.y() > self.start_position.y() and point.y() < self.start_position.y() + height    )

    def mouseMoveEvent(self, event):

        if self.on_selection:
            self.last_position = event.pos()
            self.update()

    def mousePressEvent(self, QMouseEvent):

        if not self.insideSelection(QMouseEvent.pos()):
            self.on_selection = True
            self.selected = True
            self.start_position = QMouseEvent.pos()
            self.last_position = QMouseEvent.pos()
            self.update()

    def mouseDoubleClickEvent(self, QMouseEvent):
        if self.insideSelection(QMouseEvent.pos()):
            width = self.last_position.x() - self.start_position.x()
            height = self.last_position.y() - self.start_position.y()
            self.c.cropImage.emit(self.start_position.x(), self.start_position.y(), width,height)

    def mouseReleaseEvent(self, QMouseEvent):
        self.on_selection = False
        self.update()

    def enterEvent(self, event):
        return super().enterEvent(event)

    def leaveEvent(self, event):
        return super().enterEvent(event)

    def paintEvent(self, e):
        qp = QPainter()
        qp.begin(self)
        #self.drawWidget(qp)
        if self.selected:
            qp.setCompositionMode(QPainter.CompositionMode_HardLight)
            qp.setBrush(QColor(0, 0, 0, 128))
            qp.drawRect(0,0, self.width(), self.height())
            qp.setCompositionMode(QPainter.CompositionMode_Overlay)
            qp.setBrush(QColor(255, 255, 255, 255))

            width = self.last_position.x() - self.start_position.x()
            height = self.last_position.y()-self.start_position.y()

            qp.drawRect(self.start_position.x(), self.start_position.y(), width, height)
            qp.setCompositionMode(QPainter.CompositionMode_SourceOver)

            image_w = min([abs(width), abs(height), self.crop.width()]) #self.crop.width()
            image_h = image_w #self.crop.height()
            qp.drawPixmap(self.start_position.x() + width/2 - image_w/2, self.start_position.y() + height/2 - image_h/2, image_w, image_h, self.crop)

        qp.end()
 def mouseMoveEvent(self, event):
     delta = QPoint (event.globalPos() - self.oldPos)
     self.move(self.x() + delta.x(), self.y() + delta.y())
     self.oldPos = event.globalPos()
Esempio n. 33
0
File: gui.py Progetto: fqez/sandbox
class RenderArea(QWidget):
	  
	Line, Points, Polyline, Polygon, Rect, RoundedRect, Ellipse, Arc, Chord, \
			Pie, Path, Text, Pixmap = range(13)
  
	def __init__(self, machine, parent=None):
		super(RenderArea, self).__init__(parent)
  
		self.pen = QPen()
		self.brush = QBrush()
		
		self.antialiased = True
  
		self.setBackgroundRole(QPalette.Base)
		self.setAutoFillBackground(True)
		
		self.machine = machine

		self.dist_radius = min(self.width() / 4, self.height() / 4) * 1.5
		self.dist_center = QPoint(self.width() / 2.0, self.height() / 2.0)
		self.n_states = len(self.machine.getStates())

		self.state_radius = self.funcc(self.dist_radius, self.n_states)
		self.active = -1
		self.t_active = -1

		self.pts = []


		#Brushes
		linearGradient = QLinearGradient(-self.state_radius, -self.state_radius, self.state_radius, self.state_radius)
		linearGradient.setColorAt(0.0, Qt.darkGreen)
		linearGradient.setColorAt(0.7, Qt.green)
		linearGradient.setColorAt(0.3, Qt.green)
		linearGradient.setColorAt(1.0, Qt.white)
		self.greenGradientBrush = QBrush(linearGradient)

		linearGradient = QLinearGradient(-self.state_radius, -self.state_radius, self.state_radius, self.state_radius)
		linearGradient.setColorAt(0.0, Qt.darkGray)
		linearGradient.setColorAt(0.7, Qt.lightGray)
		linearGradient.setColorAt(0.3, Qt.gray)
		linearGradient.setColorAt(1.0, Qt.white)
		self.grayGradientBrush = QBrush(linearGradient)
		self.setBrush(self.grayGradientBrush)
		#end brushes

	def funcc(self, r, n):
		return int((r*0.05) / (n*0.04))

	def minimumSizeHint(self):
		return QSize(100, 100)
  
	def sizeHint(self):
		return QSize(400, 200)
  
	def setPen(self, pen):
		self.pen = pen
		self.update()
  
	def setBrush(self, brush):
		self.brush = brush
		self.update()
 
	def resizeEvent(self, event):
		self.dist_center = QPoint(self.width() / 2.0, self.height() / 2.0)
		self.dist_radius = min(self.width() / 4, self.height() / 4) * 1.5
		self.state_radius = self.funcc(self.dist_radius, self.n_states)
		self.update()

	def poly(self, pts):
		return QPolygonF(map(lambda p: QPointF(*p), pts))

	def wave(self):
		
		t = self.machine.getActiveTransition()
		if t != None:

			init = QPoint(t.getOrig()[0], t.getOrig()[1])
			end = QPoint(t.getDest()[0], t.getDest()[1])
			angle = t.getAngle()
			#print('processing transition', t.id, t.orig, t.dest)
			while t.isActive():
			#for i in range(3):	#for testing
				self.pts = [[init.x(), init.y()], [end.x(), end.y()]]
				if self.pts[0][0] <= self.pts[1][0] and self.pts[0][1] >= self.pts[1][1]:
					while self.pts[0][0] <= self.pts[1][0] and self.pts[0][1] >= self.pts[1][1]:
						self.sumPoint(angle)
				elif self.pts[0][0] <= self.pts[1][0] and self.pts[0][1] <= self.pts[1][1]:
					while self.pts[0][0] <= self.pts[1][0] and self.pts[0][1] <= self.pts[1][1]:
						self.sumPoint(angle)
				elif self.pts[0][0] >= self.pts[1][0] and self.pts[0][1] >= self.pts[1][1]:
					while self.pts[0][0] >= self.pts[1][0] and self.pts[0][1] >= self.pts[1][1]:
						self.sumPoint(angle)
				elif self.pts[0][0] >= self.pts[1][0] and self.pts[0][1] <= self.pts[1][1]:
					while self.pts[0][0] >= self.pts[1][0] and self.pts[0][1] <= self.pts[1][1]:
						self.sumPoint(angle)
						

	def sumPoint(self, angle):
		self.pts[0][0] += (self.state_radius * math.cos(angle) * 0.1)
		self.pts[0][1] -= (self.state_radius * math.sin(angle) * 0.1)
		self.update()
		QApplication.processEvents()
		time.sleep(0.025)

	def paintEvent(self, event):
		  
		painter = QPainter(self)
		painter.setPen(self.pen)
		painter.setBrush(self.brush)
		if self.antialiased:
			painter.setRenderHint(QPainter.Antialiasing)

		angle_step = 360 / self.n_states

		painter.save()	#Save_1. Save the state of the system (push matrix)
		painter.translate(self.dist_center.x(), self.dist_center.y())		# go to the center of the render area
		painter.rotate(-180)	#to start painting from the left side of the circle (clockwise)

		#center of the circumference where through we are going to paint our states 
		x = self.dist_radius * math.cos(0)	
		y = self.dist_radius * math.sin(0)


		for h in range(self.n_states):

			rot = angle_step * h 	# each state is equidistant from the others. We paint them in circles

			painter.save()			#Save_2
			painter.rotate(rot)		#now our system is pointing to the next state to be drawn
			painter.translate(x,y)	#now our origin is in the center of the next state to be drawn

			#if the state is active, fill it green
			if self.machine.getState(h).isActive():	
				painter.setBrush(self.greenGradientBrush)			
			painter.drawEllipse(QPoint(0,0), self.state_radius, self.state_radius)	#draw the new state

			#global position of transformed coordinates (before any transformation, origin at top-left corner)
			gx = painter.worldTransform().map(QPoint(0,0)).x()
			gy = painter.worldTransform().map(QPoint(0,0)).y()
			self.machine.getState(h).setPos(gx, gy)		#store the center of the state without any transformation applied

			# text transformation. Our origin is still in the center of the current state
			painter.save()			#Save_3
			painter.rotate(180)		#making the text go vertical
			painter.rotate(-rot)	#undoing the rotation made for painting the state. No the text is horizontal
			font = painter.font();
			font.setPixelSize(self.state_radius*.4);
			painter.setFont(font);
			rect = QRect(-self.state_radius, -self.state_radius, self.state_radius*2, self.state_radius*2)
			painter.drawText(rect, Qt.AlignCenter, self.machine.getState(h).getName());
			painter.restore()	#Restore_3
			#end text transformation

			painter.restore()	#Restore_2
			
		painter.restore()	#Restore_1. Restore the state of the system (pop matrix)

		
		#drawing transitions. Line between states
		painter.save()	# Save_4
		pptv = QTransform()		#Define a new transformation. Needed to rotate the system along other axis than Z
		pptv.translate(0, self.height())	#We are now at the bottom-left corner of the screen
		pptv.rotate(-180, Qt.XAxis)			#Rotate along the X-axis so now we are in a typical cartesian system.
		painter.setTransform(pptv)			#Apply the transformation
		states = self.machine.getStates()
		for state in states:
			transitions = state.getTransitions()
			for transition in transitions:
				#get the center of the origin and destination states in our current system state
				orig = QPoint(state.getPos()[0], state.getPos()[1])
				end = QPoint(self.machine.getState(transition.getStateEnd()).getPos()[0], self.machine.getState(transition.getStateEnd()).getPos()[1])
				# get those coordinates without transformation
				orig2 = QPoint(painter.worldTransform().map(orig))
				end2 = QPoint(painter.worldTransform().map(end))

				#get the angle between states centers and the horizon
				angle = math.atan2(end2.y() - orig2.y(), end2.x() - orig2.x())

				#get the coordinates of the starting point of the transition (it starts in the bound of the state, not in the center)
				newX = self.state_radius * math.cos(angle) + orig2.x()
				newY = self.state_radius * math.sin(angle) + orig2.y()
				#now the transition starts at the border, not in the center
				orig2.setX(newX)
				orig2.setY(newY)

				#same for the destination state
				angle2 = math.atan2(orig2.y() - end2.y(), orig2.x() - end2.x())
				newX2 = self.state_radius * math.cos(angle2) + end2.x()
				newY2 = self.state_radius * math.sin(angle2) + end2.y()
				end2.setX(newX2)
				end2.setY(newY2)

				#draw the line between the origin and destination states
				painter.drawLine(orig2, end2)
				#get the start and the end of the transition untransformed
				init = QPoint(painter.worldTransform().map(orig2))
				end = QPoint(painter.worldTransform().map(end2))
				#store that info
				transition.setOrig(init.x(), init.y())
				transition.setDest(end.x(), end.y())	
				transition.setAngle(angle)
		painter.restore() #Restore_4


		#Appliying style to the transitions
		painter.setPen(QPen(QColor(Qt.gray), 3))
		for state in self.machine.getStates():
			for transition in state.getTransitions():
				#get the start and end coordinates of the transition
				i = QPoint(transition.getOrig()[0], transition.getOrig()[1])
				o = QPoint(transition.getDest()[0], transition.getDest()[1])			
				painter.drawPolyline(i, o)

				#Drawing the arrow at the end of the transition
				painter.save()	#Save_5
				painter.setPen(QPen(QColor(Qt.gray), 2))
				painter.translate(transition.getDest()[0],transition.getDest()[1])	#Go to the end of the transition
				painter.rotate(90 - transition.getAngle()*180/math.pi)		#Rotate to point in the direction of the transition

				#coordinates of the arrow (triangle)
				a = QPoint(0,0)
				b = QPoint(-5,10)
				c = QPoint(5,10)

				#coordinates of the arrow untransformed
				a1 = painter.worldTransform().map(a)
				b1 = painter.worldTransform().map(b)
				c1 = painter.worldTransform().map(c)

				#Drawin the actual arrow
				pointer = QPolygon([a,b,c])
				painter.drawPolygon(pointer)
				painter.restore()	#Restore_5

				#For the animation of the transition
				painter.save()	#Save_6
				if transition.isActive():	#if the current transition is the active one the wave function will be running, so it's updating the canvas

					painter.setPen(QPen(QColor(Qt.green), 3))
					painter.drawPolyline(i,o)
					
					painter.setPen(QPen(QColor(Qt.gray), 3))
					painter.drawPolyline(self.poly(self.pts))

					#Draw the arrow in the active state (red arrow)
					painter.setBrush(QBrush(QColor(255, 0, 0)))
					painter.setPen(QPen(QColor(Qt.red), 2))
					pointer = QPolygon([a1,b1,c1])
					painter.drawPolygon(pointer)
					
					#Ball that follows the line animation
					for x, y in self.pts:
						painter.drawEllipse(QRectF(self.pts[0][0] - 4, self.pts[0][1] - 4, 8, 8))
				painter.restore()	#Restore_6

				#Painting the text of the transition
				painter.save()	#Save_7
				pptv = QTransform()
				painter.setPen(QPen(QColor(Qt.black), 3))
				#get the middle point of the transition
				middleX = (transition.getOrig()[0] + transition.getDest()[0]) /2	
				middleY = (transition.getOrig()[1] + transition.getDest()[1]) /2
				pptv.translate(middleX, middleY)	#translate to that point
				painter.setTransform(pptv)			#apply the transformation
				font = painter.font();
				font.setPixelSize(self.state_radius*.2);
				painter.setFont(font);
				rect = QRect(-self.state_radius, -self.state_radius, self.state_radius*2, self.state_radius*2)
				name = str(transition.getId())+ '. ' + transition.getName()
				painter.drawText(rect, Qt.AlignCenter, name)
				painter.restore()	#Restore_7


  
		#paint the actual canvas
		painter.setPen(self.palette().dark().color())
		painter.setBrush(Qt.NoBrush)
		painter.drawRect(QRect(0, 0, self.width() - 1, self.height() - 1))


	def start(self,n):
		'''print('active', n)
		self.active = n%3
		self.deactivateAll()
		self.machine.setStateActive(self.active, True)
		#time.sleep(5)
		self.t_active = n%3
		self.wave()

		for i in range(self.n_states):
			print('active', i)
			self.active = i
			self.deactivateAll()
			self.machine.setStateActive(self.active, True)
			self.update()
			QApplication.processEvents()
			time.sleep(2)

			self.t_active = i
			self.deactivateAll()
			self.machine.setTransitionActive  (self.t_active, True)
			for i in self.machine.getTransitions():
				print (i.isActive())
			self.update()
			QApplication.processEvents()
			self.wave()'''

	def stop(self):
		self.machine.deactivateAll()
Esempio n. 34
0
class GLWidget(QOpenGLWidget):
    def __init__(self, systemModel, parent=None):
        super(GLWidget, self).__init__(parent)

        self.setFixedSize(systemModel.view_width, systemModel.view_height)

        self.systemModel = systemModel
        self.min_method = None
        self.min_options = None
        self.errval0 = None
        self.errval1 = None
        self.errval = None
        self.iter_count = 0
        self.image = None
        self.image_file = None

        self._show_target_image = True
        self.full_image = None
        self.image_bg_threshold = None
        self.latest_rendered_image = None

        self.im_def_scale = systemModel.view_width / systemModel.cam.width
        self.im_scale = self.im_def_scale
        self.im_xoff = 0
        self.im_yoff = 0
        self.im_width = systemModel.cam.width
        self.im_height = systemModel.cam.height

        self.debug_c = 0
        self.gl = None
        self._paint_entered = False

        self._render = True
        self._algo_render = False
        self._center_model = False
        self._discretize_tol = False
        self.latest_discretization_err_q = False

        self.add_image_noise = True
        self._noise_image = os.path.join(SCRIPT_DIR, '../data/noise-fg.png')

        self._width = None
        self._height = None
        self._side = None
        self._gl_image = None
        self._object = None
        self._lastPos = QPoint()
        self._imgColor = QColor.fromRgbF(1, 1, 1, 0.4)
        self._fgColor = QColor.fromRgbF(0.6, 0.6, 0.6, 1)
        self._bgColor = QColor.fromRgbF(0, 0, 0, 1)
        #self._bgColor = QColor.fromCmykF(0.0, 0.0, 0.0, 1.0)
        self._frustum_near = 0.1
        self._frustum_far = self.systemModel.max_distance
        self._expire = 0

    def minimumSizeHint(self):
        return self.sizeHint()

    def maximumSizeHint(self):
        return self.sizeHint()

    def sizeHint(self):
        return QSize(self.systemModel.view_width, self.systemModel.view_height)

    def initializeGL(self):
        f = QSurfaceFormat()
        #f.setVersion(2, 2)
        f.setDepthBufferSize(32)
        p = QOpenGLVersionProfile(f)
        self.gl = self.context().versionFunctions(p)
        self.gl.initializeOpenGLFunctions()

        self.setClearColor(self._bgColor)
        self.loadObject()
        if not BATCH_MODE:
            self.loadTargetImageMeta(
                self.systemModel.asteroid.sample_image_meta_file)

        self.gl.glEnable(self.gl.GL_CULL_FACE)

        # for transparent asteroid image on top of model
        self.gl.glBlendFunc(self.gl.GL_SRC_ALPHA,
                            self.gl.GL_ONE_MINUS_SRC_ALPHA)

        if self._render:
            self._rendOpts()
        else:
            self._projOpts()

        if not BATCH_MODE:
            self.loadTargetImage(self.systemModel.asteroid.sample_image_file)
#            if not USE_IMG_LABEL_FOR_SC_POS:
#                CentroidAlgo.update_sc_pos(self.systemModel, self.full_image)

    def _projOpts(self):
        # reset from potentially set rendering options
        self.gl.glDisable(self.gl.GL_LIGHTING)
        self.gl.glDisable(self.gl.GL_DEPTH_TEST)
        self.gl.glShadeModel(self.gl.GL_FLAT)

    def _rendOpts(self):
        # rendering options
        self.gl.glEnable(self.gl.GL_LIGHTING)
        self.gl.glEnable(self.gl.GL_DEPTH_TEST)
        self.gl.glShadeModel(self.gl.GL_SMOOTH)  # TODO: try with flat
        self.gl.glEnable(self.gl.GL_LIGHT0)

    def resizeGL(self, width, height):
        rel_scale = self.im_scale / self.im_def_scale
        self.im_def_scale = min(width / self.systemModel.cam.width,
                                height / self.systemModel.cam.height)
        self.im_scale = self.im_def_scale * rel_scale
        self._width = width
        self._height = height
        self._side = min(width, height)
        self.updateFrustum()

    def updateFrustum(self):
        # calculate frustum based on fov, aspect & near
        # NOTE: with wide angle camera, would need to take into account
        #       im_xoff, im_yoff, im_width and im_height
        x_fov = self.systemModel.cam.x_fov * self.im_def_scale / self.im_scale
        y_fov = self.systemModel.cam.y_fov * self.im_def_scale / self.im_scale

        # calculate frustum based on fov, aspect & near
        right = self._frustum_near * math.tan(math.radians(x_fov / 2))
        top = self._frustum_near * math.tan(math.radians(y_fov / 2))
        self._frustum = {
            'left': -right,
            'right': right,
            'bottom': -top,
            'top': top,
        }

        if self._width is not None:
            self.gl.glViewport((self._width - self._side) // 2,
                               (self._height - self._side) // 2, self._side,
                               self._side)

        self.gl.glMatrixMode(self.gl.GL_PROJECTION)
        self.gl.glLoadIdentity()
        self.gl.glFrustum(self._frustum['left'], self._frustum['right'],
                          self._frustum['bottom'], self._frustum['top'],
                          self._frustum_near, self._frustum_far)
        self.gl.glMatrixMode(self.gl.GL_MODELVIEW)

    def renderParams(self):
        m = self.systemModel

        # NOTE: with wide angle camera, would need to take into account
        #       im_xoff, im_yoff, im_width and im_height
        xc_off = (self.im_xoff + self.im_width / 2 - m.cam.width / 2)
        xc_angle = xc_off / m.cam.width * math.radians(m.cam.x_fov)

        yc_off = (self.im_yoff + self.im_height / 2 - m.cam.height / 2)
        yc_angle = yc_off / m.cam.height * math.radians(m.cam.y_fov)

        # first rotate around x-axis, then y-axis,
        # note that diff angle in image y direction corresponds to rotation
        # around x-axis and vise versa
        q_crop = (np.quaternion(math.cos(-yc_angle / 2), math.sin(
            -yc_angle / 2), 0, 0) * np.quaternion(math.cos(-xc_angle / 2), 0,
                                                  math.sin(-xc_angle / 2), 0))

        x = m.x_off.value
        y = m.y_off.value
        z = m.z_off.value

        # rotate offsets using q_crop
        x, y, z = tools.q_times_v(q_crop.conj(), np.array([x, y, z]))

        # maybe put object in center of view
        if self._center_model:
            x, y = 0, 0

        # get object rotation and turn it a bit based on cropping effect
        q, err_q = m.gl_sc_asteroid_rel_q(self._discretize_tol)
        if self._discretize_tol:
            self.latest_discretization_err_q = err_q

        qfin = (q * q_crop.conj())
        rv = tools.q_to_angleaxis(qfin)

        # light direction
        light, _ = m.gl_light_rel_dir(err_q)

        res = (light, (x, y, z), (math.degrees(rv[0]), ) + tuple(rv[1:]))
        return res

    def paintGL(self):
        if self._algo_render:
            self.gl.glDisable(self.gl.GL_BLEND)
        else:
            self.gl.glEnable(self.gl.GL_BLEND)

        self.gl.glClear(self.gl.GL_COLOR_BUFFER_BIT
                        | self.gl.GL_DEPTH_BUFFER_BIT)

        light, transl, rot = self.renderParams()

        self.gl.glLoadIdentity()

        # sunlight config
        if self._render or self._algo_render:
            self.gl.glLightfv(self.gl.GL_LIGHT0, self.gl.GL_POSITION,
                              tuple(-light) + (0, ))
            self.gl.glLightfv(self.gl.GL_LIGHT0, self.gl.GL_SPOT_DIRECTION,
                              tuple(light))
            self.gl.glLightfv(self.gl.GL_LIGHT0, self.gl.GL_DIFFUSE,
                              (.4, .4, .4, 1))
            self.gl.glLightfv(self.gl.GL_LIGHT0, self.gl.GL_AMBIENT,
                              (0, 0, 0, 1))
            self.gl.glLightModelfv(self.gl.GL_LIGHT_MODEL_AMBIENT,
                                   (0, 0, 0, 1))

        self.gl.glTranslated(*transl)
        self.gl.glRotated(*rot)
        if self._object is not None:
            self.gl.glCallList(self._object)

        if not self._algo_render and self._gl_image is not None:
            self.gl.glLoadIdentity()
            self.setColor(self._imgColor)
            #            self.gl.glRasterPos3f(self._frustum['left'],
            #                                  self._frustum['bottom'], -self._frustum_near)
            self.gl.glWindowPos2f(0, 0)
            self.gl.glDrawPixels(self._image_w, self._image_h, self.gl.GL_RGBA,
                                 self.gl.GL_UNSIGNED_BYTE, self._gl_image)

        # dont need? commented out glFinish as it takes around 4s to run
        # after win10 "creators update"
        #self.gl.glFinish()

    def saveView(self, grayscale=True, depth=False):
        self.makeCurrent()

        # for some reason following gives 24 and not 32 bits
        # f = self.format()
        # print('dbs: %s'%f.depthBufferSize())

        pixels = glReadPixels(
            0, 0, self.systemModel.view_width, self.systemModel.view_height,
            self.gl.GL_DEPTH_COMPONENT if depth else
            self.gl.GL_LUMINANCE if grayscale else self.gl.GL_RGBA,
            self.gl.GL_FLOAT if depth else self.gl.GL_UNSIGNED_BYTE)

        data = np.frombuffer(pixels, dtype=('float32' if depth else 'uint8'))

        if depth:
            near = self._frustum_near
            far = self._frustum_far
            a = -(far - near) / (2.0 * far * near)
            b = (far + near) / (2.0 * far * near)
            data = np.divide(1.0,
                             (2.0 * a) * data - (a - b))  # 1/((2*X-1)*a+b)

        data = np.flipud(
            data.reshape(
                [self.systemModel.view_height, self.systemModel.view_width] +
                ([] if depth or grayscale else [4])))

        # print('data: %s'%(data,))
        # cv2.imshow('target_image', data)
        # cv2.waitKey()

        return data

    def saveViewOld(self):
        fbo = self.grabFramebuffer()  # calls paintGL
        buffer = QBuffer()
        buffer.open(QIODevice.ReadWrite)
        fbo.save(buffer, "PNG", quality=100)

        # TODO: find a more efficient way than
        # bytes => buffer => PNG => nparray => cvimage
        # - maybe here's some ideas:
        #       https://vec.io/posts/faster-alternatives-to-glreadpixels\
        #                                       -and-glteximage2d-in-opengl-es

        imdata = np.frombuffer(buffer.data(), dtype='int8')
        view = cv2.imdecode(imdata, cv2.IMREAD_GRAYSCALE)
        return view

    def saveViewTest(self):
        if False:
            # this takes around double the time than current way
            fbo = self.grabFramebuffer()
            arr = fbo.constBits().asarray(512 * 512 * 4)
            view = [0] * 256
            for i in range(1, 512 * 512 * 4, 4):
                view[arr[i]] += 1
        elif False:
            # glReadPixels doesnt exist
            arr = self.gl.glReadPixels(0, 0, 512, 512, self.gl.GL_RGB,
                                       self.gl.GL_UNSIGNED_BYTE)
            view = [0] * 256
            for i in range(1, 512 * 512 * 3, 3):
                view[arr[i]] += 1

        return view

    def saveViewToFile(self, imgfile):
        cv2.imwrite(imgfile, self.render(center=False))

    def render(self, center=True, depth=False, discretize_tol=False):
        if not self._render:
            self._rendOpts()
        self._algo_render = True
        self._discretize_tol = discretize_tol
        tmp = self._center_model
        self._center_model = center

        fbo = self.grabFramebuffer()  # calls paintGL
        self.latest_rendered_image = rr = self.saveView(depth=False)
        if depth:
            dr = self.saveView(depth=True)

        self._center_model = tmp
        self._discretize_tol = False
        self._algo_render = False
        if not self._render:
            self._projOpts()
        return (rr, dr) if depth else rr

    def mousePressEvent(self, event):
        self._lastPos = event.pos()

    def mouseMoveEvent(self, event):
        dx = event.x() - self._lastPos.x()
        dy = event.y() - self._lastPos.y()

        if event.buttons() & (Qt.LeftButton | Qt.RightButton):
            self.systemModel.x_rot.value = \
                    (self.systemModel.x_rot.value + dy/2 + 90) % 180 - 90

            param = 'y_rot' if event.buttons() & Qt.LeftButton else 'z_rot'
            getattr(self.systemModel, param).value = \
                    (getattr(self.systemModel, param).value + dx/2) % 360

            self.update()

        self._lastPos = event.pos()

    def setImageZoomAndResolution(self,
                                  im_xoff=0,
                                  im_yoff=0,
                                  im_width=None,
                                  im_height=None,
                                  im_scale=1):

        self.im_xoff = im_xoff
        self.im_yoff = im_yoff
        self.im_width = im_width or self.systemModel.cam.width
        self.im_height = im_height or self.systemModel.cam.height
        self.im_scale = im_scale

        self.image = ImageProc.crop_and_zoom_image(self.full_image,
                                                   self.im_xoff, self.im_yoff,
                                                   self.im_width,
                                                   self.im_height,
                                                   self.im_scale)
        self._image_h = self.image.shape[0]
        self._image_w = self.image.shape[1]

        if self._show_target_image:
            # form _gl_image that is used for rendering
            # black => 0 alpha, non-black => white => .5 alpha
            im = self.image.copy()
            alpha = np.zeros(im.shape, im.dtype)
            #im[im > 0] = 255
            alpha[im > 0] = 128
            self._gl_image = np.flipud(cv2.merge(
                (im, im, im, alpha))).tobytes()

        self.updateFrustum()

        # WORK-AROUND: for some reason wont use new frustum if window not resized
        s = self.parent().size()
        self.parent().resize(s.width() + 1, s.height())
        self.parent().resize(s.width(), s.height())
        self.update()
        QCoreApplication.processEvents()

    def loadTargetImage(self, src, remove_bg=True):
        tmp = cv2.imread(src, cv2.IMREAD_GRAYSCALE)
        if tmp is None:
            raise Exception('Cant load image from file %s' % (src, ))

        cam = self.systemModel.cam
        if tmp.shape != (cam.height, cam.width):
            # visit fails to generate 1024 high images
            tmp = cv2.resize(tmp,
                             None,
                             fx=cam.width / tmp.shape[1],
                             fy=cam.height / tmp.shape[0],
                             interpolation=cv2.INTER_CUBIC)

        if BATCH_MODE and self.add_image_noise and self._noise_image:
            tmp = ImageProc.add_noise_to_image(tmp, self._noise_image)

        self.image_file = src
        if remove_bg:
            self.full_image, h, th = ImageProc.process_target_image(tmp)
            self.image_bg_threshold = th
            self.parent().centroid.bg_threshold = th
        else:
            self.full_image = tmp
            self.image_bg_threshold = None
            self.parent().centroid.bg_threshold = None

        self.setImageZoomAndResolution(im_scale=self.im_def_scale)

    def loadTargetImageMeta(self, src):
        if True:
            # FIX: currently doesnt correspond with what is shown
            lblloader.load_image_meta(src, self.systemModel)
        else:
            self.systemModel.ast_x_rot.value = -83.88
            self.systemModel.ast_y_rot.value = 74.38
            self.systemModel.ast_z_rot.value = -77.98
            self.systemModel.time.range = (1437391848.27 * 0.99,
                                           1437391848.27 * 1.01)
            self.systemModel.time.value = 1437391848.27
            self.systemModel.x_off.value = -0.42
            self.systemModel.x_rot.value = -49.39
            self.systemModel.y_off.value = 2.47
            self.systemModel.y_rot.value = 123.26
            self.systemModel.z_off.value = -158.39
            self.systemModel.z_rot.value = -96.62

        self.update()

    def loadObject(self, noisy_model=None):
        genList = self.gl.glGenLists(1)
        self.gl.glNewList(genList, self.gl.GL_COMPILE)
        self.gl.glBegin(self.gl.GL_TRIANGLES)  # GL_POLYGON?
        self.setColor(self._fgColor)
        #self.gl.glEnable(self.gl.GL_COLOR_MATERIAL);
        #self.gl.glMaterialfv(self.gl.GL_FRONT, self.gl.GL_SPECULAR, (0,0,0,1));
        #self.gl.glMaterialfv(self.gl.GL_FRONT, self.gl.GL_SHININESS, (0,));

        if self.systemModel.asteroid.real_shape_model is None:
            rsm = self.systemModel.asteroid.real_shape_model = objloader.ShapeModel(
                fname=self.systemModel.asteroid.target_model_file)
        else:
            rsm = self.systemModel.asteroid.real_shape_model

        if noisy_model is not None:
            sm = noisy_model


#        elif self._add_shape_model_noise and not BATCH_MODE:
#sup = objloader.ShapeModel(fname=SHAPE_MODEL_NOISE_SUPPORT)
#sm, noise, L = tools.apply_noise(rsm, support=np.array(sup.vertices))
#            sm, noise, L = tools.apply_noise(rsm)
        else:
            sm = rsm

        for triangle, norm, tx in sm.faces:
            self.triangle(sm.vertices[triangle[0]], sm.vertices[triangle[1]],
                          sm.vertices[triangle[2]], sm.normals[norm])

        self.gl.glEnd()
        self.gl.glEndList()

        if DEBUG:
            # assume all 32bit (4B) variables, no reuse of vertices
            # => triangle count x (3 vertices + 1 normal) x 3d vectors x bytes per variable
            mem_needed = len(sm.faces) * 4 * 3 * 4
            print('3D model mem use: %.0fx %.0fB => %.1fMB' %
                  (len(sm.faces), 4 * 3 * 4, mem_needed / 1024 / 1024))

        self._object = genList

    def triangle(self, x1, x2, x3, n):
        self.gl.glNormal3f(*n)
        self.gl.glVertex3f(*x1)
        self.gl.glVertex3f(*x2)
        self.gl.glVertex3f(*x3)

    def setClearColor(self, c):
        self.gl.glClearColor(c.redF(), c.greenF(), c.blueF(), c.alphaF())

    def setColor(self, c):
        self.gl.glColor4f(c.redF(), c.greenF(), c.blueF(), c.alphaF())
Esempio n. 35
0
    def drawGrid(self, painter, exposed, gridColor):
        rect = exposed.toAlignedRect()
        if (rect.isNull()):
            return
        p = RenderParams(self.map())
        # Determine the tile and pixel coordinates to start at
        startTile = self.screenToTileCoords_(rect.topLeft()).toPoint()
        startPos = self.tileToScreenCoords_(startTile).toPoint()
        ## Determine in which half of the tile the top-left corner of the area we
        # need to draw is. If we're in the upper half, we need to start one row
        # up due to those tiles being visible as well. How we go up one row
        # depends on whether we're in the left or right half of the tile.
        ##
        inUpperHalf = rect.y() - startPos.y() < p.sideOffsetY
        inLeftHalf = rect.x() - startPos.x() < p.sideOffsetX
        if (inUpperHalf):
            startTile.setY(startTile.y() - 1)
        if (inLeftHalf):
            startTile.setX(startTile.x() - 1)
        startTile.setX(max(0, startTile.x()))
        startTile.setY(max(0, startTile.y()))
        startPos = self.tileToScreenCoords_(startTile).toPoint()
        oct = [
            QPoint(0, p.tileHeight - p.sideOffsetY),
            QPoint(0, p.sideOffsetY),
            QPoint(p.sideOffsetX, 0),
            QPoint(p.tileWidth - p.sideOffsetX, 0),
            QPoint(p.tileWidth, p.sideOffsetY),
            QPoint(p.tileWidth, p.tileHeight - p.sideOffsetY),
            QPoint(p.tileWidth - p.sideOffsetX, p.tileHeight),
            QPoint(p.sideOffsetX, p.tileHeight)
        ]

        lines = QVector()
        #lines.reserve(8)
        gridColor.setAlpha(128)
        gridPen = QPen(gridColor)
        gridPen.setCosmetic(True)
        _x = QVector()
        _x.append(2)
        _x.append(2)
        gridPen.setDashPattern(_x)
        painter.setPen(gridPen)
        if (p.staggerX):
            # Odd row shifting is applied in the rendering loop, so un-apply it here
            if (p.doStaggerX(startTile.x())):
                startPos.setY(startPos.y() - p.rowHeight)
            while (startPos.x() <= rect.right()
                   and startTile.x() < self.map().width()):
                rowTile = QPoint(startTile)
                rowPos = QPoint(startPos)
                if (p.doStaggerX(startTile.x())):
                    rowPos.setY(rowPos.y() + p.rowHeight)
                while (rowPos.y() <= rect.bottom()
                       and rowTile.y() < self.map().height()):
                    lines.append(QLineF(rowPos + oct[1], rowPos + oct[2]))
                    lines.append(QLineF(rowPos + oct[2], rowPos + oct[3]))
                    lines.append(QLineF(rowPos + oct[3], rowPos + oct[4]))
                    isStaggered = p.doStaggerX(startTile.x())
                    lastRow = rowTile.y() == self.map().height() - 1
                    lastColumn = rowTile.x() == self.map().width() - 1
                    bottomLeft = rowTile.x() == 0 or (lastRow and isStaggered)
                    bottomRight = lastColumn or (lastRow and isStaggered)
                    if (bottomRight):
                        lines.append(QLineF(rowPos + oct[5], rowPos + oct[6]))
                    if (lastRow):
                        lines.append(QLineF(rowPos + oct[6], rowPos + oct[7]))
                    if (bottomLeft):
                        lines.append(QLineF(rowPos + oct[7], rowPos + oct[0]))
                    painter.drawLines(lines)
                    lines.resize(0)
                    rowPos.setY(rowPos.y() + p.tileHeight + p.sideLengthY)
                    rowTile.setY(rowTile.y() + 1)

                startPos.setX(startPos.x() + p.columnWidth)
                startTile.setX(startTile.x() + 1)
        else:
            # Odd row shifting is applied in the rendering loop, so un-apply it here
            if (p.doStaggerY(startTile.y())):
                startPos.setX(startPos.x() - p.columnWidth)
            while (startPos.y() <= rect.bottom()
                   and startTile.y() < self.map().height()):
                rowTile = QPoint(startTile)
                rowPos = QPoint(startPos)
                if (p.doStaggerY(startTile.y())):
                    rowPos.setX(rowPos.x() + p.columnWidth)
                while (rowPos.x() <= rect.right()
                       and rowTile.x() < self.map().width()):
                    lines.append(QLineF(rowPos + oct[0], rowPos + oct[1]))
                    lines.append(QLineF(rowPos + oct[1], rowPos + oct[2]))
                    lines.append(QLineF(rowPos + oct[3], rowPos + oct[4]))
                    isStaggered = p.doStaggerY(startTile.y())
                    lastRow = rowTile.y() == self.map().height() - 1
                    lastColumn = rowTile.x() == self.map().width() - 1
                    bottomLeft = lastRow or (rowTile.x() == 0
                                             and not isStaggered)
                    bottomRight = lastRow or (lastColumn and isStaggered)
                    if (lastColumn):
                        lines.append(QLineF(rowPos + oct[4], rowPos + oct[5]))
                    if (bottomRight):
                        lines.append(QLineF(rowPos + oct[5], rowPos + oct[6]))
                    if (bottomLeft):
                        lines.append(QLineF(rowPos + oct[7], rowPos + oct[0]))
                    painter.drawLines(lines)
                    lines.resize(0)
                    rowPos.setX(rowPos.x() + p.tileWidth + p.sideLengthX)
                    rowTile.setX(rowTile.x() + 1)

                startPos.setY(startPos.y() + p.rowHeight)
                startTile.setY(startTile.y() + 1)
class PersonalInformationManager(QObject):
    """
    Class implementing the personal information manager used to complete form
    fields.
    """
    FullName = 0
    LastName = 1
    FirstName = 2
    Email = 3
    Mobile = 4
    Phone = 5
    Address = 6
    City = 7
    Zip = 8
    State = 9
    Country = 10
    HomePage = 11
    Special1 = 12
    Special2 = 13
    Special3 = 14
    Special4 = 15
    Max = 16
    Invalid = 256

    def __init__(self, parent=None):
        """
        Constructor
        
        @param parent reference to the parent object (QObject)
        """
        super(PersonalInformationManager, self).__init__(parent)

        self.__loaded = False
        self.__allInfo = {}
        self.__infoMatches = {}
        self.__translations = {}

        self.__view = None
        self.__clickedPos = QPoint()

    def __loadSettings(self):
        """
        Private method to load the settings.
        """
        self.__allInfo[self.FullName] = Preferences.getWebBrowser(
            "PimFullName")
        self.__allInfo[self.LastName] = Preferences.getWebBrowser(
            "PimLastName")
        self.__allInfo[self.FirstName] = Preferences.getWebBrowser(
            "PimFirstName")
        self.__allInfo[self.Email] = Preferences.getWebBrowser("PimEmail")
        self.__allInfo[self.Mobile] = Preferences.getWebBrowser("PimMobile")
        self.__allInfo[self.Phone] = Preferences.getWebBrowser("PimPhone")
        self.__allInfo[self.Address] = Preferences.getWebBrowser("PimAddress")
        self.__allInfo[self.City] = Preferences.getWebBrowser("PimCity")
        self.__allInfo[self.Zip] = Preferences.getWebBrowser("PimZip")
        self.__allInfo[self.State] = Preferences.getWebBrowser("PimState")
        self.__allInfo[self.Country] = Preferences.getWebBrowser("PimCountry")
        self.__allInfo[self.HomePage] = Preferences.getWebBrowser(
            "PimHomePage")
        self.__allInfo[self.Special1] = Preferences.getWebBrowser(
            "PimSpecial1")
        self.__allInfo[self.Special2] = Preferences.getWebBrowser(
            "PimSpecial2")
        self.__allInfo[self.Special3] = Preferences.getWebBrowser(
            "PimSpecial3")
        self.__allInfo[self.Special4] = Preferences.getWebBrowser(
            "PimSpecial4")

        self.__translations[self.FullName] = self.tr("Full Name")
        self.__translations[self.LastName] = self.tr("Last Name")
        self.__translations[self.FirstName] = self.tr("First Name")
        self.__translations[self.Email] = self.tr("E-mail")
        self.__translations[self.Mobile] = self.tr("Mobile")
        self.__translations[self.Phone] = self.tr("Phone")
        self.__translations[self.Address] = self.tr("Address")
        self.__translations[self.City] = self.tr("City")
        self.__translations[self.Zip] = self.tr("ZIP Code")
        self.__translations[self.State] = self.tr("State/Region")
        self.__translations[self.Country] = self.tr("Country")
        self.__translations[self.HomePage] = self.tr("Home Page")
        self.__translations[self.Special1] = self.tr("Custom 1")
        self.__translations[self.Special2] = self.tr("Custom 2")
        self.__translations[self.Special3] = self.tr("Custom 3")
        self.__translations[self.Special4] = self.tr("Custom 4")

        self.__infoMatches[self.FullName] = ["fullname", "realname"]
        self.__infoMatches[self.LastName] = ["lastname", "surname"]
        self.__infoMatches[self.FirstName] = ["firstname", "name"]
        self.__infoMatches[self.Email] = ["email", "e-mail", "mail"]
        self.__infoMatches[self.Mobile] = ["mobile", "mobilephone"]
        self.__infoMatches[self.Phone] = ["phone", "telephone"]
        self.__infoMatches[self.Address] = ["address"]
        self.__infoMatches[self.City] = ["city"]
        self.__infoMatches[self.Zip] = ["zip"]
        self.__infoMatches[self.State] = ["state", "region"]
        self.__infoMatches[self.Country] = ["country"]
        self.__infoMatches[self.HomePage] = ["homepage", "www"]

        self.__loaded = True

    def showConfigurationDialog(self):
        """
        Public method to show the configuration dialog.
        """
        from .PersonalDataDialog import PersonalDataDialog
        dlg = PersonalDataDialog()
        if dlg.exec_() == QDialog.Accepted:
            dlg.storeData()
            self.__loadSettings()

    def createSubMenu(self, menu, view, hitTestResult):
        """
        Public method to create the personal information sub-menu.
        
        @param menu reference to the main menu (QMenu)
        @param view reference to the view (HelpBrowser)
        @param hitTestResult reference to the hit test result
            (WebHitTestResult)
        """
        self.__view = view
        self.__clickedPos = hitTestResult.pos()

        if not hitTestResult.isContentEditable():
            return

        if not self.__loaded:
            self.__loadSettings()

        submenu = QMenu(self.tr("Insert Personal Information"), menu)
        submenu.setIcon(UI.PixmapCache.getIcon("pim.png"))

        for key, info in sorted(self.__allInfo.items()):
            if info:
                act = submenu.addAction(self.__translations[key])
                act.setData(info)
                act.triggered.connect(lambda: self.__insertData(act))

        submenu.addSeparator()
        submenu.addAction(self.tr("Edit Personal Information"),
                          self.showConfigurationDialog)

        menu.addMenu(submenu)
        menu.addSeparator()

    def __insertData(self, act):
        """
        Private slot to insert the selected personal information.
        
        @param act reference to the action that triggered
        @type QAction
        """
        if self.__view is None or self.__clickedPos.isNull():
            return

        info = act.data()
        info = info.replace('"', '\\"')

        source = """
            var e = document.elementFromPoint({0}, {1});
            if (e) {{
                var v = e.value.substring(0, e.selectionStart);
                v += "{2}" + e.value.substring(e.selectionEnd);
                e.value = v;
            }}""".format(self.__clickedPos.x(), self.__clickedPos.y(), info)
        self.__view.page().runJavaScript(source, WebBrowserPage.SafeJsWorld)

    def viewKeyPressEvent(self, view, evt):
        """
        Protected method to handle key press events we are interested in.
        
        @param view reference to the view (HelpBrowser)
        @param evt reference to the key event (QKeyEvent)
        @return flag indicating handling of the event (boolean)
        """
        if view is None:
            return False

        isEnter = evt.key() in [Qt.Key_Return, Qt.Key_Enter]
        isControlModifier = evt.modifiers() & Qt.ControlModifier
        if not isEnter or not isControlModifier:
            return False

        if not self.__loaded:
            self.__loadSettings()

        source = """
            var inputs = document.getElementsByTagName('input');
            var table = {0};
            for (var i = 0; i < inputs.length; ++i) {{
                var input = inputs[i];
                if (input.type != 'text' || input.name == '')
                    continue;
                for (var key in table) {{
                    if (!table.hasOwnProperty(key))
                        continue;
                    if (key == input.name || input.name.indexOf(key) != -1) {{
                        input.value = table[key];
                        break;
                    }}
                }}
            }}""".format(self.__matchingJsTable())
        view.page().runJavaScript(source, WebBrowserPage.SafeJsWorld)

        return True

    def connectPage(self, page):
        """
        Public method to allow the personal information manager to connect to
        the page.
        
        @param page reference to the web page
        @type WebBrowserPage
        """
        page.loadFinished.connect(lambda ok: self.__pageLoadFinished(ok, page))

    def __pageLoadFinished(self, ok, page):
        """
        Private slot to handle the completion of a page load.
        
        @param ok flag indicating a successful load
        @type bool
        @param page reference to the web page object
        @type WebBrowserPage
        """
        if page is None or not ok:
            return

        if not self.__loaded:
            self.__loadSettings()

        source = """
            var inputs = document.getElementsByTagName('input');
            var table = {0};
            for (var i = 0; i < inputs.length; ++i) {{
                var input = inputs[i];
                if (input.type != 'text' || input.name == '')
                    continue;
                for (var key in table) {{
                    if (!table.hasOwnProperty(key) || table[key] == '')
                        continue;
                    if (key == input.name || input.name.indexOf(key) != -1) {{
                        input.style['-webkit-appearance'] = 'none';
                        input.style['-webkit-box-shadow'] =
                            'inset 0 0 2px 1px #000EEE';
                        break;
                    }}
                }}
            }}""".format(self.__matchingJsTable())
        page.runJavaScript(source, WebBrowserPage.SafeJsWorld)

    def __matchingJsTable(self):
        """
        Private method to create the common part of the JavaScript sources.
        
        @return JavaScript source
        @rtype str
        """
        values = []
        for key, names in self.__infoMatches.items():
            for name in names:
                value = self.__allInfo[key].replace('"', '\\"')
                values.append('"{0}":"{1}"'.format(name, value))
        return "{{ {0} }}".format(",".join(values))
Esempio n. 37
0
class ImageWithMouseControl(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.left_click = False
        self.parent = parent
        self.img = QPixmap(img_url)
        self.scaled_img = self.img.scaled(self.size())
        self.point = QPoint(0, 0)

    def paintEvent(self, e):
        '''
        绘图
        :param e:
        :return:
        '''
        painter = QPainter()
        painter.begin(self)
        self.draw_img(painter)
        painter.end()

    def draw_img(self, painter):
        painter.drawPixmap(self.point, self.scaled_img)

    def mouseMoveEvent(self, e):  # 重写移动事件
        if self.left_click:
            self._endPos = e.pos() - self._startPos
            self.point = self.point + self._endPos
            self._startPos = e.pos()
            self.repaint()

    def mousePressEvent(self, e):
        if e.button() == Qt.LeftButton:
            self.left_click = True
            self._startPos = e.pos()
        else:
            print('an xia qu')

    def mouseReleaseEvent(self, e):
        print(e.button())
        global count_num
        if e.button() == Qt.LeftButton:
            self.left_click = False
        elif e.button() == Qt.RightButton:  # 右键标记
            print('song kai ')
            self.mark_node(e.x(), e.y())
            self.img = QPixmap('D:/23.jpg')
            self.scaled_img = self.img.scaled(img_hight * rate,
                                              img_width * rate)
            self.repaint()
            count_num = count_num + 1

    def get_pre_img(self):
        self.img = QPixmap('D:/23.jpg')
        self.scaled_img = self.img.scaled(img_hight * rate, img_width * rate)
        self.repaint()

    def revoke_node(self):
        global node_list, count_num
        if len(node_list) != 0:
            node_list.pop()
        image_mark.Image_mark.mark_function(node_list, img_url, sizz)
        self.img = QPixmap('D:/23.jpg')
        self.scaled_img = self.img.scaled(img_hight * rate, img_width * rate)
        self.repaint()
        count_num = count_num - 1

    def wheelEvent(self, e):
        global rate
        if e.angleDelta().y() > 0:
            # 放大图片
            rate = rate + 0.05
            self.scaled_img = self.img.scaled(img_hight * rate,
                                              img_width * rate)
            new_w = e.x() - (self.scaled_img.width() *
                             (e.x() - self.point.x())) / (
                                 self.scaled_img.width() / 0.99)
            new_h = e.y() - (self.scaled_img.height() *
                             (e.y() - self.point.y())) / (
                                 self.scaled_img.height() / 0.99)
            self.point = QPoint(new_w, new_h)
            self.repaint()
        elif e.angleDelta().y() < 0:
            # 缩小图片
            rate = rate - 0.05
            self.scaled_img = self.img.scaled(img_hight * rate,
                                              img_width * rate)
            new_w = e.x() - (self.scaled_img.width() *
                             (e.x() - self.point.x())) / (
                                 self.scaled_img.width() * 0.99)
            new_h = e.y() - (self.scaled_img.height() *
                             (e.y() - self.point.y())) / (
                                 self.scaled_img.height() * 0.99)
            self.point = QPoint(new_w, new_h)
            self.repaint()

    def resizeEvent(self, e):
        if self.parent is not None:
            self.scaled_img = self.img.scaled(self.size())
            self.point = QPoint(0, 0)
            self.update()

    def mark_node(self, x, y):  # 标点
        global node_list
        tx = (x - self.point.x()) / (rate * k)
        ty = (y - self.point.y()) / (rate * k)
        # print(tx,ty)
        node_list.append((tx, ty))
        # try:
        image_mark.Image_mark.mark_function(node_list, img_url, sizz)  # 文件写入
Esempio n. 38
0
 def update_seed(self, seed: QPoint):
     self.seed_point = seed
     self.seed_x.setText(str(seed.x()))
     self.seed_y.setText(str(seed.y()))
Esempio n. 39
0
class GLWidget(CanvasBase):
    CAM_LEFT_X = -0.5
    CAM_RIGHT_X = 0.5
    CAM_BOTTOM_Y = 0.5
    CAM_TOP_Y = -0.5
    CAM_NEAR_Z = -14.0
    CAM_FAR_Z = 14.0

    COLOR_BACKGROUND = QColor.fromHsl(160, 0, 255, 255)
    COLOR_NORMAL = QColor.fromCmykF(1.0, 0.5, 0.0, 0.0, 1.0)
    COLOR_SELECT = QColor.fromCmykF(0.0, 1.0, 0.9, 0.0, 1.0)
    COLOR_NORMAL_DISABLED = QColor.fromCmykF(1.0, 0.5, 0.0, 0.0, 0.25)
    COLOR_SELECT_DISABLED = QColor.fromCmykF(0.0, 1.0, 0.9, 0.0, 0.25)
    COLOR_ENTRY_ARROW = QColor.fromRgbF(0.0, 0.0, 1.0, 1.0)
    COLOR_EXIT_ARROW = QColor.fromRgbF(0.0, 1.0, 0.0, 1.0)
    COLOR_ROUTE = QColor.fromRgbF(0.5, 0.0, 0.0, 1.0)
    COLOR_STMOVE = QColor.fromRgbF(0.5, 0.0, 0.25, 1.0)
    COLOR_BREAK = QColor.fromRgbF(1.0, 0.0, 1.0, 0.7)
    COLOR_LEFT = QColor.fromHsl(134, 240, 130, 255)
    COLOR_RIGHT = QColor.fromHsl(186, 240, 130, 255)

    def __init__(self, parent=None):
        super(GLWidget, self).__init__(parent)

        self.shapes = Shapes([])
        self.orientation = 0
        self.wpZero = 0
        self.routearrows = []
        self.expprv = None

        self.isPanning = False
        self.isRotating = False
        self.isMultiSelect = False
        self._lastPos = QPoint()

        self.posX = 0.0
        self.posY = 0.0
        self.posZ = 0.0
        self.rotX = 0.0
        self.rotY = 0.0
        self.rotZ = 0.0
        self.scale = 1.0
        self.scaleCorr = 1.0

        self.showPathDirections = False
        self.showDisabledPaths = False

        self.topLeft = Point()
        self.bottomRight = Point()

        self.tol = 0

    def tr(self, string_to_translate):
        """
        Translate a string using the QCoreApplication translation framework
        @param string_to_translate: a unicode string
        @return: the translated unicode string if it was possible to translate
        """
        return text_type(QCoreApplication.translate('GLWidget',
                                                    string_to_translate))

    def resetAll(self):
        # the wpzero is currently generated "last"
        if self.wpZero > 0:
            GL.glDeleteLists(self.orientation + 1, self.wpZero - self.orientation)
        self.shapes = Shapes([])
        self.wpZero = 0
        self.delete_opt_paths()

        self.posX = 0.0
        self.posY = 0.0
        self.posZ = 0.0
        self.rotX = 0.0
        self.rotY = 0.0
        self.rotZ = 0.0
        self.scale = 1.0

        self.topLeft = Point()
        self.bottomRight = Point()

        self.update()

    def delete_opt_paths(self):
        if len(self.routearrows) > 0:
            GL.glDeleteLists(self.routearrows[0][2], len(self.routearrows))
            self.routearrows = []

    def addexproutest(self):
        self.expprv = Point3D(g.config.vars.Plane_Coordinates['axis1_start_end'],
                              g.config.vars.Plane_Coordinates['axis2_start_end'],
                              0)

    def addexproute(self, exp_order, layer_nr):
        """
        This function initialises the Arrows of the export route order and its numbers.
        """
        for shape_nr in range(len(exp_order)):
            shape = self.shapes[exp_order[shape_nr]]
            st = self.expprv
            en, self.expprv = shape.get_start_end_points_physical()
            en = en.to3D(shape.axis3_start_mill_depth)
            self.expprv = self.expprv.to3D(shape.axis3_mill_depth)

            self.routearrows.append([st, en, 0])

            # TODO self.routetext.append(RouteText(text=("%s,%s" % (layer_nr, shape_nr+1)), startp=en))

    def addexprouteen(self):
        st = self.expprv
        en = Point3D(g.config.vars.Plane_Coordinates['axis1_start_end'],
                     g.config.vars.Plane_Coordinates['axis2_start_end'],
                     0)

        self.routearrows.append([st, en, 0])
        for route in self.routearrows:
            route[2] = self.makeRouteArrowHead(route[0], route[1])

    def contextMenuEvent(self, event):
        if not self.isRotating:
            clicked, offset, _ = self.getClickedDetails(event)
            MyDropDownMenu(self, event.globalPos(), clicked, offset)

    def setXRotation(self, angle):
        self.rotX = self.normalizeAngle(angle)

    def setYRotation(self, angle):
        self.rotY = self.normalizeAngle(angle)

    def setZRotation(self, angle):
        self.rotZ = self.normalizeAngle(angle)

    def normalizeAngle(self, angle):
        return (angle - 180) % -360 + 180

    def mousePressEvent(self, event):
        if self.isPanning or self.isRotating:
            self.setCursor(Qt.ClosedHandCursor)
        elif event.button() == Qt.LeftButton:
            clicked, offset, tol = self.getClickedDetails(event)
            xyForZ = {}
            for shape in self.shapes:
                hit = False
                z = shape.axis3_start_mill_depth
                if z not in xyForZ:
                    xyForZ[z] = self.determineSelectedPosition(clicked, z, offset)
                hit |= shape.isHit(xyForZ[z], tol)

                if not hit:
                    z = shape.axis3_mill_depth
                    if z not in xyForZ:
                        xyForZ[z] = self.determineSelectedPosition(clicked, z, offset)
                    hit |= shape.isHit(xyForZ[z], tol)

                if self.isMultiSelect and shape.selected:
                    hit = not hit

                if hit != shape.selected:
                    g.window.TreeHandler.updateShapeSelection(shape, hit)

                shape.selected = hit

            self.update()
        self._lastPos = event.pos()

    def getClickedDetails(self, event):
        min_side = min(self.frameSize().width(), self.frameSize().height())
        clicked = Point((event.pos().x() - self.frameSize().width() / 2),
                        (event.pos().y() - self.frameSize().height() / 2)) / min_side / self.scale
        offset = Point3D(-self.posX, -self.posY, -self.posZ) / self.scale
        tol = 4 * self.scaleCorr / min_side / self.scale
        return clicked, offset, tol

    def determineSelectedPosition(self, clicked, forZ, offset):
        angleX = -radians(self.rotX)
        angleY = -radians(self.rotY)

        zv = forZ - offset.z
        clickedZ = ((zv + clicked.x * sin(angleY)) / cos(angleY) - clicked.y * sin(angleX)) / cos(angleX)
        sx, sy, sz = self.deRotate(clicked.x, clicked.y, clickedZ)
        return Point(sx + offset.x, - sy - offset.y)  #, sz + offset.z

    def mouseReleaseEvent(self, event):
        if event.button() == Qt.LeftButton or event.button() == Qt.RightButton:
            if self.isPanning:
                self.setCursor(Qt.OpenHandCursor)
            elif self.isRotating:
                self.setCursor(Qt.PointingHandCursor)

    def mouseMoveEvent(self, event):
        dx = event.pos().x() - self._lastPos.x()
        dy = event.pos().y() - self._lastPos.y()

        if self.isRotating:
            if event.buttons() == Qt.LeftButton:
                self.setXRotation(self.rotX - dy / 2)
                self.setYRotation(self.rotY + dx / 2)
            elif event.buttons() == Qt.RightButton:
                self.setXRotation(self.rotX - dy / 2)
                self.setZRotation(self.rotZ + dx / 2)
        elif self.isPanning:
            if event.buttons() == Qt.LeftButton:
                min_side = min(self.frameSize().width(), self.frameSize().height())
                dx, dy, dz = self.deRotate(dx, dy, 0)
                self.posX += dx / min_side
                self.posY += dy / min_side
                self.posZ += dz / min_side

        self._lastPos = event.pos()
        self.update()

    def wheelEvent(self, event):
        min_side = min(self.frameSize().width(), self.frameSize().height())
        x = (event.pos().x() - self.frameSize().width() / 2) / min_side
        y = (event.pos().y() - self.frameSize().height() / 2) / min_side
        s = 1.001 ** event.angleDelta().y()

        x, y, z = self.deRotate(x, y, 0)
        self.posX = (self.posX - x) * s + x
        self.posY = (self.posY - y) * s + y
        self.posZ = (self.posZ - z) * s + z
        self.scale *= s

        self.update()

    def rotate(self, x, y, z):
        angleZ = radians(self.rotZ)
        x, y, z = x*cos(angleZ) - y*sin(angleZ), x*sin(angleZ) + y*cos(angleZ), z
        angleY = radians(self.rotY)
        x, y, z = x*cos(angleY) + z*sin(angleY), y, -x*sin(angleY) + z*cos(angleY)
        angleX = radians(self.rotX)
        return x, y*cos(angleX) - z*sin(angleX), y*sin(angleX) + z*cos(angleX)

    def deRotate(self, x, y, z):
        angleX = -radians(self.rotX)
        x, y, z = x, y*cos(angleX) - z*sin(angleX), y*sin(angleX) + z*cos(angleX)
        angleY = -radians(self.rotY)
        x, y, z = x*cos(angleY) + z*sin(angleY), y, -x*sin(angleY) + z*cos(angleY)
        angleZ = -radians(self.rotZ)
        return x*cos(angleZ) - y*sin(angleZ), x*sin(angleZ) + y*cos(angleZ), z

    def getRotationVectors(self, orgRefVector, toRefVector):
        """
        Generate a rotation matrix such that toRefVector = matrix * orgRefVector
        @param orgRefVector: A 3D unit vector
        @param toRefVector: A 3D unit vector
        @return: 3 vectors such that matrix = [vx; vy; vz]
        """
        # based on:
        # http://math.stackexchange.com/questions/180418/calculate-rotation-matrix-to-align-vector-a-to-vector-b-in-3d

        if orgRefVector == toRefVector:
            return Point3D(1, 0, 0), Point3D(0, 1, 0), Point3D(0, 0, 1)

        v = orgRefVector.cross_product(toRefVector)
        mn = (1 - orgRefVector * toRefVector) / v.length_squared()

        vx = Point3D(1, -v.z, v.y) + mn * Point3D(-v.y**2 - v.z**2, v.x * v.y, v.x * v.z)
        vy = Point3D(v.z, 1, -v.x) + mn * Point3D(v.x * v.y, -v.x**2 - v.z**2, v.y * v.z)
        vz = Point3D(-v.y, v.x, 1) + mn * Point3D(v.x * v.z, v.y * v.z, -v.x**2 - v.y**2)

        return vx, vy, vz

    def initializeGL(self):
        logger.debug(self.tr("Using OpenGL version: %s") % GL.glGetString(GL.GL_VERSION).decode("utf-8"))
        self.setClearColor(GLWidget.COLOR_BACKGROUND)

        GL.glEnable(GL.GL_MULTISAMPLE)

        GL.glEnable(GL.GL_POLYGON_SMOOTH)
        GL.glHint(GL.GL_POLYGON_SMOOTH_HINT, GL.GL_NICEST)
        # GL.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_LINE)
        GL.glShadeModel(GL.GL_SMOOTH)

        GL.glEnable(GL.GL_DEPTH_TEST)
        GL.glEnable(GL.GL_CULL_FACE)
        # GL.glEnable(GL.GL_LIGHTING)
        # GL.glEnable(GL.GL_LIGHT0)
        GL.glEnable(GL.GL_BLEND)
        GL.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA)
        # GL.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, (0.5, 5.0, 7.0, 1.0))
        # GL.glEnable(GL.GL_NORMALIZE)

        self.drawOrientationArrows()

    def paintGL(self):
        # The last transformation you specify takes place first.
        GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT)
        GL.glLoadIdentity()
        GL.glRotatef(self.rotX, 1.0, 0.0, 0.0)
        GL.glRotatef(self.rotY, 0.0, 1.0, 0.0)
        GL.glRotatef(self.rotZ, 0.0, 0.0, 1.0)
        GL.glTranslatef(self.posX, self.posY, self.posZ)
        GL.glScalef(self.scale, self.scale, self.scale)
        for shape in self.shapes.selected_iter():
            if not shape.disabled:
                self.setColor(GLWidget.COLOR_STMOVE)
                GL.glCallList(shape.drawStMove)
                self.setColor(GLWidget.COLOR_SELECT)
                GL.glCallList(shape.drawObject)
            elif self.showDisabledPaths:
                self.setColor(GLWidget.COLOR_SELECT_DISABLED)
                GL.glCallList(shape.drawObject)
        for shape in self.shapes.not_selected_iter():
            if not shape.disabled:
                if shape.parentLayer.isBreakLayer():
                    self.setColor(GLWidget.COLOR_BREAK)
                elif shape.cut_cor == 41:
                    self.setColor(GLWidget.COLOR_LEFT)
                elif shape.cut_cor == 42:
                    self.setColor(GLWidget.COLOR_RIGHT)
                else:
                    self.setColor(GLWidget.COLOR_NORMAL)
                GL.glCallList(shape.drawObject)
                if self.showPathDirections:
                    self.setColor(GLWidget.COLOR_STMOVE)
                    GL.glCallList(shape.drawStMove)
            elif self.showDisabledPaths:
                self.setColor(GLWidget.COLOR_NORMAL_DISABLED)
                GL.glCallList(shape.drawObject)

        # optimization route arrows
        self.setColor(GLWidget.COLOR_ROUTE)
        GL.glBegin(GL.GL_LINES)
        for route in self.routearrows:
            start = route[0]
            end = route[1]
            GL.glVertex3f(start.x, -start.y, start.z)
            GL.glVertex3f(end.x, -end.y, end.z)
        GL.glEnd()

        GL.glScalef(self.scaleCorr / self.scale, self.scaleCorr / self.scale, self.scaleCorr / self.scale)
        scaleArrow = self.scale / self.scaleCorr
        for route in self.routearrows:
            end = scaleArrow * route[1]
            GL.glTranslatef(end.x, -end.y, end.z)
            GL.glCallList(route[2])
            GL.glTranslatef(-end.x, end.y, -end.z)

        # direction arrows
        for shape in self.shapes:
            if shape.selected and (not shape.disabled or self.showDisabledPaths) or\
               self.showPathDirections and not shape.disabled:
                start, end = shape.get_start_end_points_physical()
                start = scaleArrow * start.to3D(shape.axis3_start_mill_depth)
                end = scaleArrow * end.to3D(shape.axis3_mill_depth)
                GL.glTranslatef(start.x, -start.y, start.z)
                GL.glCallList(shape.drawArrowsDirection[0])
                GL.glTranslatef(-start.x, start.y, -start.z)
                GL.glTranslatef(end.x, -end.y, end.z)
                GL.glCallList(shape.drawArrowsDirection[1])
                GL.glTranslatef(-end.x, end.y, -end.z)

        if self.wpZero > 0:
            GL.glCallList(self.wpZero)
        GL.glTranslatef(-self.posX / self.scaleCorr, -self.posY / self.scaleCorr, -self.posZ / self.scaleCorr)
        GL.glCallList(self.orientation)

    def resizeGL(self, width, height):
        GL.glViewport(0, 0, width, height)
        side = min(width, height)
        GL.glMatrixMode(GL.GL_PROJECTION)
        GL.glLoadIdentity()
        if width >= height:
            scale_x = width / height
            GL.glOrtho(GLWidget.CAM_LEFT_X * scale_x, GLWidget.CAM_RIGHT_X * scale_x,
                            GLWidget.CAM_BOTTOM_Y, GLWidget.CAM_TOP_Y,
                            GLWidget.CAM_NEAR_Z, GLWidget.CAM_FAR_Z)
        else:
            scale_y = height / width
            GL.glOrtho(GLWidget.CAM_LEFT_X, GLWidget.CAM_RIGHT_X,
                            GLWidget.CAM_BOTTOM_Y * scale_y, GLWidget.CAM_TOP_Y * scale_y,
                            GLWidget.CAM_NEAR_Z, GLWidget.CAM_FAR_Z)
        self.scaleCorr = 400 / side
        GL.glMatrixMode(GL.GL_MODELVIEW)

    def setClearColor(self, c):
        GL.glClearColor(c.redF(), c.greenF(), c.blueF(), c.alphaF())

    def setColor(self, c):
        self.setColorRGBA(c.redF(), c.greenF(), c.blueF(), c.alphaF())

    def setColorRGBA(self, r, g, b, a):
        # GL.glMaterialfv(GL.GL_FRONT, GL.GL_DIFFUSE, (r, g, b, a))
        GL.glColor4f(r, g, b, a)

    def plotAll(self, shapes):
        for shape in shapes:
            self.paint_shape(shape)
            self.shapes.append(shape)
        self.drawWpZero()

    def repaint_shape(self, shape):
        GL.glDeleteLists(shape.drawObject, 4)
        self.paint_shape(shape)

    def paint_shape(self, shape):
        shape.drawObject = self.makeShape(shape)  # 1 object
        shape.stmove = StMove(shape)
        shape.drawStMove = self.makeStMove(shape.stmove)  # 1 object
        shape.drawArrowsDirection = self.makeDirArrows(shape)  # 2 objects

    def makeShape(self, shape):
        genList = GL.glGenLists(1)
        GL.glNewList(genList, GL.GL_COMPILE)

        GL.glBegin(GL.GL_LINES)
        shape.make_path(self.drawHorLine, self.drawVerLine)
        GL.glEnd()

        GL.glEndList()

        self.topLeft.detTopLeft(shape.topLeft)
        self.bottomRight.detBottomRight(shape.bottomRight)

        return genList

    def makeStMove(self, stmove):
        genList = GL.glGenLists(1)
        GL.glNewList(genList, GL.GL_COMPILE)

        GL.glBegin(GL.GL_LINES)
        stmove.make_path(self.drawHorLine, self.drawVerLine)
        GL.glEnd()

        GL.glEndList()

        return genList

    def drawHorLine(self, caller, Ps, Pe):
        GL.glVertex3f(Ps.x, -Ps.y, caller.axis3_start_mill_depth)
        GL.glVertex3f(Pe.x, -Pe.y, caller.axis3_start_mill_depth)
        GL.glVertex3f(Ps.x, -Ps.y, caller.axis3_mill_depth)
        GL.glVertex3f(Pe.x, -Pe.y, caller.axis3_mill_depth)

    def drawVerLine(self, caller, Ps):
        GL.glVertex3f(Ps.x, -Ps.y, caller.axis3_start_mill_depth)
        GL.glVertex3f(Ps.x, -Ps.y, caller.axis3_mill_depth)

    def drawOrientationArrows(self):

        rCone = 0.01
        rCylinder = 0.004
        zTop = 0.05
        zMiddle = 0.02
        zBottom = -0.03
        segments = 20

        arrow = GL.glGenLists(1)
        GL.glNewList(arrow, GL.GL_COMPILE)

        self.drawCone(Point(), rCone, zTop, zMiddle, segments)
        self.drawSolidCircle(Point(), rCone, zMiddle, segments)
        self.drawCylinder(Point(), rCylinder, zMiddle, zBottom, segments)
        self.drawSolidCircle(Point(), rCylinder, zBottom, segments)

        GL.glEndList()

        self.orientation = GL.glGenLists(1)
        GL.glNewList(self.orientation, GL.GL_COMPILE)

        self.setColorRGBA(0.0, 0.0, 1.0, 0.5)
        GL.glCallList(arrow)

        GL.glRotatef(90, 0, 1, 0)
        self.setColorRGBA(1.0, 0.0, 0.0, 0.5)
        GL.glCallList(arrow)

        GL.glRotatef(90, 1, 0, 0)
        self.setColorRGBA(0.0, 1.0, 0.0, 0.5)
        GL.glCallList(arrow)

        GL.glEndList()

    def drawWpZero(self):

        r = 0.02
        segments = 20  # must be a multiple of 4

        self.wpZero = GL.glGenLists(1)
        GL.glNewList(self.wpZero, GL.GL_COMPILE)

        self.setColorRGBA(0.2, 0.2, 0.2, 0.7)
        self.drawSphere(r, segments, segments // 4, segments, segments // 4)

        GL.glBegin(GL.GL_TRIANGLE_FAN)
        GL.glVertex3f(0, 0, 0)
        for i in range(segments // 4 + 1):
            ang = -i * 2 * pi / segments
            xy2 = Point().get_arc_point(ang, r)
            # GL.glNormal3f(0, -1, 0)
            GL.glVertex3f(xy2.x, 0, xy2.y)
        for i in range(segments // 4 + 1):
            ang = -i * 2 * pi / segments
            xy2 = Point().get_arc_point(ang, r)
            # GL.glNormal3f(-1, 0, 0)
            GL.glVertex3f(0, -xy2.y, -xy2.x)
        for i in range(segments // 4 + 1):
            ang = -i * 2 * pi / segments
            xy2 = Point().get_arc_point(ang, r)
            # GL.glNormal3f(0, 0, 1)
            GL.glVertex3f(-xy2.y, xy2.x, 0)
        GL.glEnd()

        self.setColorRGBA(0.6, 0.6, 0.6, 0.5)
        self.drawSphere(r * 1.25, segments, segments, segments, segments)

        GL.glEndList()

    def drawSphere(self, r, lats, mlats, longs, mlongs):
        lats //= 2
        # based on http://www.cburch.com/cs/490/sched/feb8/index.html
        for i in range(mlats):
            lat0 = pi * (-0.5 + i / lats)
            z0 = r * sin(lat0)
            zr0 = r * cos(lat0)
            lat1 = pi * (-0.5 + (i + 1) / lats)
            z1 = r * sin(lat1)
            zr1 = r * cos(lat1)
            GL.glBegin(GL.GL_QUAD_STRIP)
            for j in range(mlongs + 1):
                lng = 2 * pi * j / longs
                x = cos(lng)
                y = sin(lng)

                GL.glNormal3f(x * zr0, y * zr0, z0)
                GL.glVertex3f(x * zr0, y * zr0, z0)
                GL.glNormal3f(x * zr1, y * zr1, z1)
                GL.glVertex3f(x * zr1, y * zr1, z1)
            GL.glEnd()

    def drawSolidCircle(self, origin, r, z, segments):
        GL.glBegin(GL.GL_TRIANGLE_FAN)
        # GL.glNormal3f(0, 0, -1)
        GL.glVertex3f(origin.x, -origin.y, z)
        for i in range(segments + 1):
            ang = -i * 2 * pi / segments
            xy2 = origin.get_arc_point(ang, r)
            GL.glVertex3f(xy2.x, -xy2.y, z)
        GL.glEnd()

    def drawCone(self, origin, r, zTop, zBottom, segments):
        GL.glBegin(GL.GL_TRIANGLE_FAN)
        GL.glVertex3f(origin.x, -origin.y, zTop)
        for i in range(segments + 1):
            ang = i * 2 * pi / segments
            xy2 = origin.get_arc_point(ang, r)

            # GL.glNormal3f(xy2.x, -xy2.y, zBottom)
            GL.glVertex3f(xy2.x, -xy2.y, zBottom)
        GL.glEnd()

    def drawCylinder(self, origin, r, zTop, zBottom, segments):
        GL.glBegin(GL.GL_QUAD_STRIP)
        for i in range(segments + 1):
            ang = i * 2 * pi / segments
            xy = origin.get_arc_point(ang, r)

            # GL.glNormal3f(xy.x, -xy.y, 0)
            GL.glVertex3f(xy.x, -xy.y, zTop)
            GL.glVertex3f(xy.x, -xy.y, zBottom)
        GL.glEnd()

    def makeDirArrows(self, shape):
        (start, start_dir), (end, end_dir) = shape.get_start_end_points_physical(None, False)

        startArrow = GL.glGenLists(1)
        GL.glNewList(startArrow, GL.GL_COMPILE)
        self.setColor(GLWidget.COLOR_ENTRY_ARROW)
        self.drawDirArrow(Point3D(), start_dir.to3D(), True)
        GL.glEndList()

        endArrow = GL.glGenLists(1)
        GL.glNewList(endArrow, GL.GL_COMPILE)
        self.setColor(GLWidget.COLOR_EXIT_ARROW)
        self.drawDirArrow(Point3D(), end_dir.to3D(), False)
        GL.glEndList()

        return startArrow, endArrow

    def drawDirArrow(self, origin, direction, startError):
        offset = 0.0 if startError else 0.05
        zMiddle = -0.02 + offset
        zBottom = -0.05 + offset
        rx, ry, rz = self.getRotationVectors(Point3D(0, 0, 1), direction)

        self.drawArrowHead(origin, rx, ry, rz, offset)

        GL.glBegin(GL.GL_LINES)
        zeroMiddle = Point3D(0, 0, zMiddle)
        GL.glVertex3f(zeroMiddle * rx + origin.x, -zeroMiddle * ry - origin.y, zeroMiddle * rz + origin.z)
        zeroBottom = Point3D(0, 0, zBottom)
        GL.glVertex3f(zeroBottom * rx + origin.x, -zeroBottom * ry - origin.y, zeroBottom * rz + origin.z)
        GL.glEnd()

    def makeRouteArrowHead(self, start, end):
        if end == start:
            direction = Point3D(0, 0, 1)
        else:
            direction = (end - start).unit_vector()
        rx, ry, rz = self.getRotationVectors(Point3D(0, 0, 1), direction)

        head = GL.glGenLists(1)
        GL.glNewList(head, GL.GL_COMPILE)
        self.drawArrowHead(Point3D(), rx, ry, rz, 0)
        GL.glEndList()
        return head

    def drawArrowHead(self, origin, rx, ry, rz, offset):
        r = 0.01
        segments = 10
        zTop = 0 + offset
        zBottom = -0.02 + offset

        GL.glBegin(GL.GL_TRIANGLE_FAN)
        zeroTop = Point3D(0, 0, zTop)
        GL.glVertex3f(zeroTop * rx + origin.x, -zeroTop * ry - origin.y, zeroTop * rz + origin.z)
        for i in range(segments + 1):
            ang = i * 2 * pi / segments
            xy2 = Point().get_arc_point(ang, r).to3D(zBottom)
            GL.glVertex3f(xy2 * rx + origin.x, -xy2 * ry - origin.y, xy2 * rz + origin.z)
        GL.glEnd()

        GL.glBegin(GL.GL_TRIANGLE_FAN)
        zeroBottom = Point3D(0, 0, zBottom)
        GL.glVertex3f(zeroBottom * rx + origin.x, -zeroBottom * ry - origin.y, zeroBottom * rz + origin.z)
        for i in range(segments + 1):
            ang = -i * 2 * pi / segments
            xy2 = Point().get_arc_point(ang, r).to3D(zBottom)
            GL.glVertex3f(xy2 * rx + origin.x, -xy2 * ry - origin.y, xy2 * rz + origin.z)
        GL.glEnd()

    def setShowPathDirections(self, flag):
        self.showPathDirections = flag

    def setShowDisabledPaths(self, flag=True):
        self.showDisabledPaths = flag

    def autoscale(self):
        # TODO currently only works correctly when object is not rotated
        if self.frameSize().width() >= self.frameSize().height():
            aspect_scale_x = self.frameSize().width() / self.frameSize().height()
            aspect_scale_y = 1
        else:
            aspect_scale_x = 1
            aspect_scale_y = self.frameSize().height() / self.frameSize().width()
        scaleX = (GLWidget.CAM_RIGHT_X - GLWidget.CAM_LEFT_X) * aspect_scale_x / (self.bottomRight.x - self.topLeft.x)
        scaleY = (GLWidget.CAM_BOTTOM_Y - GLWidget.CAM_TOP_Y) * aspect_scale_y / (self.topLeft.y - self.bottomRight.y)
        self.scale = min(scaleX, scaleY) * 0.95
        self.posX = ((GLWidget.CAM_LEFT_X + GLWidget.CAM_RIGHT_X) * 0.95 * aspect_scale_x
                     - (self.topLeft.x + self.bottomRight.x) * self.scale) / 2
        self.posY = -((GLWidget.CAM_TOP_Y + GLWidget.CAM_BOTTOM_Y) * 0.95 * aspect_scale_y
                      - (self.topLeft.y + self.bottomRight.y) * self.scale) / 2
        self.posZ = 0
        self.update()

    def topView(self):
        self.rotX = 0
        self.rotY = 0
        self.rotZ = 0
        self.update()

    def isometricView(self):
        self.rotX = -22
        self.rotY = -22
        self.rotZ = 0
        self.update()
Esempio n. 40
0
    def setCursorShape(self, e_pos: QPoint):
        diff = 3
        # Left - Bottom

        if (((e_pos.y() > self.y() + self.height() - diff) and # Bottom
            (e_pos.x() < self.x() + diff)) or # Left
        # Right-Bottom
        ((e_pos.y() > self.y() + self.height() - diff) and # Bottom
        (e_pos.x() > self.x() + self.width() - diff)) or # Right
        # Left-Top
        ((e_pos.y() < self.y() + diff) and # Top
        (e_pos.x() < self.x() + diff)) or # Left
        # Right-Top
        (e_pos.y() < self.y() + diff) and # Top
        (e_pos.x() > self.x() + self.width() - diff)): # Right
            # Left - Bottom
            if ((e_pos.y() > self.y() + self.height() - diff) and # Bottom
            (e_pos.x() < self.x()
                + diff)): # Left
                self.mode = Mode.RESIZEBL
                self.setCursor(QCursor(QtCore.Qt.SizeBDiagCursor))
                # Right - Bottom
            if ((e_pos.y() > self.y() + self.height() - diff) and # Bottom
            (e_pos.x() > self.x() + self.width() - diff)): # Right
                self.mode = Mode.RESIZEBR
                self.setCursor(QCursor(QtCore.Qt.SizeFDiagCursor))
            # Left - Top
            if ((e_pos.y() < self.y() + diff) and # Top
            (e_pos.x() < self.x() + diff)): # Left
                self.mode = Mode.RESIZETL
                self.setCursor(QCursor(QtCore.Qt.SizeFDiagCursor))
            # Right - Top
            if ((e_pos.y() < self.y() + diff) and # Top
            (e_pos.x() > self.x() + self.width() - diff)): # Right
                self.mode = Mode.RESIZETR
                self.setCursor(QCursor(QtCore.Qt.SizeBDiagCursor))
        # check cursor horizontal position
        elif ((e_pos.x() < self.x() + diff) or # Left
            (e_pos.x() > self.x() + self.width() - diff)): # Right
            if e_pos.x() < self.x() + diff: # Left
                self.setCursor(QCursor(QtCore.Qt.SizeHorCursor))
                self.mode = Mode.RESIZEL
            else: # Right
                self.setCursor(QCursor(QtCore.Qt.SizeHorCursor))
                self.mode = Mode.RESIZER
        # check cursor vertical position
        elif ((e_pos.y() > self.y() + self.height() - diff) or # Bottom
            (e_pos.y() < self.y() + diff)): # Top
            if e_pos.y() < self.y() + diff: # Top
                self.setCursor(QCursor(QtCore.Qt.SizeVerCursor))
                self.mode = Mode.RESIZET
            else: # Bottom
                self.setCursor(QCursor(QtCore.Qt.SizeVerCursor))
                self.mode = Mode.RESIZEB
        else:
            self.setCursor(QCursor(QtCore.Qt. ArrowCursor))
            self.mode = Mode.MOVE
Esempio n. 41
0
class SlippyMap(QObject):

    updated = pyqtSignal(QRect)

    def __init__(self, parent=None):
        super(SlippyMap, self).__init__(parent)

        self._offset = QPoint()
        self._tilesRect = QRect()
        self._tilePixmaps = {} # Point(x, y) to QPixmap mapping
        self._manager = QNetworkAccessManager()
        self._url = QUrl()
        # public vars
        self.width = 400
        self.height = 300
        self.zoom = 15
        self.latitude = 59.9138204
        self.longitude = 10.7387413

        self._emptyTile = QPixmap(TDIM, TDIM)
        self._emptyTile.fill(Qt.lightGray)

        cache = QNetworkDiskCache()
        cache.setCacheDirectory(
            QStandardPaths.writableLocation(QStandardPaths.CacheLocation))
        self._manager.setCache(cache)
        self._manager.finished.connect(self.handleNetworkData)

    def invalidate(self):
        if self.width <= 0 or self.height <= 0:
            return

        ct = tileForCoordinate(self.latitude, self.longitude, self.zoom)
        tx = ct.x()
        ty = ct.y()

        # top-left corner of the center tile
        xp = int(self.width / 2 - (tx - math.floor(tx)) * TDIM)
        yp = int(self.height / 2 - (ty - math.floor(ty)) * TDIM)

        # first tile vertical and horizontal
        xa = (xp + TDIM - 1) / TDIM
        ya = (yp + TDIM - 1) / TDIM
        xs = int(tx) - xa
        ys = int(ty) - ya

        # offset for top-left tile
        self._offset = QPoint(xp - xa * TDIM, yp - ya * TDIM)

        # last tile vertical and horizontal
        xe = int(tx) + (self.width - xp - 1) / TDIM
        ye = int(ty) + (self.height - yp - 1) / TDIM

        # build a rect
        self._tilesRect = QRect(xs, ys, xe - xs + 1, ye - ys + 1)

        if self._url.isEmpty():
            self.download()

        self.updated.emit(QRect(0, 0, self.width, self.height))

    def render(self, p, rect):
        for x in range(self._tilesRect.width()):
            for y in range(self._tilesRect.height()):
                tp = Point(x + self._tilesRect.left(), y + self._tilesRect.top())
                box = self.tileRect(tp)
                if rect.intersects(box):
                    p.drawPixmap(box, self._tilePixmaps.get(tp, self._emptyTile))
   
    def pan(self, delta):
        dx = QPointF(delta) / float(TDIM)
        center = tileForCoordinate(self.latitude, self.longitude, self.zoom) - dx
        self.latitude = latitudeFromTile(center.y(), self.zoom)
        self.longitude = longitudeFromTile(center.x(), self.zoom)
        self.invalidate()

    # slots
    def handleNetworkData(self, reply):
        img = QImage()
        tp = Point(reply.request().attribute(QNetworkRequest.User))
        url = reply.url()
        if not reply.error():
            if img.load(reply, None):
                self._tilePixmaps[tp] = QPixmap.fromImage(img)
        reply.deleteLater()
        self.updated.emit(self.tileRect(tp))

        # purge unused tiles
        bound = self._tilesRect.adjusted(-2, -2, 2, 2)
        for tp in list(self._tilePixmaps.keys()):
            if not bound.contains(tp):
                del self._tilePixmaps[tp]
        self.download()

    def download(self):
        grab = None
        for x in range(self._tilesRect.width()):
            for y in range(self._tilesRect.height()):
                tp = Point(self._tilesRect.topLeft() + QPoint(x, y))
                if tp not in self._tilePixmaps:
                    grab = QPoint(tp)
                    break

        if grab is None:
            self._url = QUrl()
            return

        path = 'http://tile.openstreetmap.org/%d/%d/%d.png' % (self.zoom, grab.x(), grab.y())
        self._url = QUrl(path)
        request = QNetworkRequest()
        request.setUrl(self._url)
        request.setRawHeader(b'User-Agent', b'Nokia (PyQt) Graphics Dojo 1.0')
        request.setAttribute(QNetworkRequest.User, grab)
        self._manager.get(request)

    def tileRect(self, tp):
        t = tp - self._tilesRect.topLeft()
        x = t.x() * TDIM + self._offset.x()
        y = t.y() * TDIM + self._offset.y()

        return QRect(x, y, TDIM, TDIM)
Esempio n. 42
0
class TContainer(QWidget):
    """ allow to move and resize by user"""
    menu = None
    mode = Mode.NONE
    position = None
    inFocus = pyqtSignal(bool)
    outFocus = pyqtSignal(bool)
    newGeometry = pyqtSignal(QRect)

    def __init__(self, parent, p, cWidget):
        super().__init__(parent=parent)

        self.menu = QMenu(parent=self, title='menu')
        self.setAttribute(QtCore.Qt.WA_DeleteOnClose, True)
        self.setVisible(True)
        self.setAutoFillBackground(False)
        self.setMouseTracking(True)
        self.setFocusPolicy(QtCore.Qt.ClickFocus)
        self.setFocus()
        self.move(p)

        self.vLayout = QVBoxLayout(self)
        self.setChildWidget(cWidget)

        self.m_infocus = True
        self.m_showMenu = False
        self.m_isEditing = True
        self.installEventFilter(parent)

    def setChildWidget(self, cWidget):
        if cWidget:
            self.childWidget = cWidget
            self.childWidget.setAttribute(QtCore.Qt.WA_TransparentForMouseEvents, True)
            self.childWidget.setParent(self)
            self.childWidget.releaseMouse()
            self.vLayout.addWidget(cWidget)
            self.vLayout.setContentsMargins(0,0,0,0)

    def popupShow(self, pt: QPoint):
        if self.menu.isEmpty:
            return
        global_ = self.mapToGlobal(pt)
        self.m_showMenu = True
        self.menu.exec(global_)
        self.m_showMenu = False

    def focusInEvent(self, a0: QtGui.QFocusEvent):
        self.m_infocus = True
        p = self.parentWidget()
        p.installEventFilter(self)
        p.repaint()
        self.inFocus.emit(True)

    def focusOutEvent(self, a0: QtGui.QFocusEvent):
        if not self.m_isEditing:
            return
        if self.m_showMenu:
            return
        self.mode = Mode.NONE
        self.outFocus.emit(False)
        self.m_infocus = False

    def paintEvent(self, e: QtGui.QPaintEvent):
        painter = QtGui.QPainter(self)
        color = (r, g, b, a) = (255, 0, 0, 16)
        painter.fillRect(e.rect(), QColor(r, g, b, a))

        if self.m_infocus:
            rect = e.rect()
            rect.adjust(0,0,-1,-1)
            painter.setPen(QColor(r, g, b))
            painter.drawRect(rect)


    def mousePressEvent(self, e: QtGui.QMouseEvent):
        self.position = QPoint(e.globalX() - self.geometry().x(), e.globalY() - self.geometry().y())
        if not self.m_isEditing:
            return
        if not self.m_infocus:
            return
        if not e.buttons() and QtCore.Qt.LeftButton:
            self.setCursorShape(e.pos())
            return
        if e.button() == QtCore.Qt.RightButton:
            self.popupShow(e.pos())
            e.accept()

    def keyPressEvent(self, e: QtGui.QKeyEvent):
        if not self.m_isEditing: return
        if e.key() == QtCore.Qt.Key_Delete:
            self.deleteLater()
        # Moving container with arrows
        if QApplication.keyboardModifiers() == QtCore.Qt.ControlModifier:
            newPos = QPoint(self.x(), self.y())
            if e.key() == QtCore.Qt.Key_Up:
                newPos.setY(newPos.y() - 1)
            if e.key() == QtCore.Qt.Key_Down:
                newPos.setY(newPos.y() + 1)
            if e.key() == QtCore.Qt.Key_Left:
                newPos.setX(newPos.x() - 1)
            if e.key() == QtCore.Qt.Key_Right:
                newPos.setX(newPos.x() + 1)
            self.move(newPos)

        if QApplication.keyboardModifiers() == QtCore.Qt.ShiftModifier:
            if e.key() == QtCore.Qt.Key_Up:
                self.resize(self.width(), self.height() - 1)
            if e.key() == QtCore.Qt.Key_Down:
                self.resize(self.width(), self.height() + 1)
            if e.key() == QtCore.Qt.Key_Left:
                self.resize(self.width() - 1, self.height())
            if e.key() == QtCore.Qt.Key_Right:
                self.resize(self.width() + 1, self.height())
        self.newGeometry.emit(self.geometry())


    def setCursorShape(self, e_pos: QPoint):
        diff = 3
        # Left - Bottom

        if (((e_pos.y() > self.y() + self.height() - diff) and # Bottom
            (e_pos.x() < self.x() + diff)) or # Left
        # Right-Bottom
        ((e_pos.y() > self.y() + self.height() - diff) and # Bottom
        (e_pos.x() > self.x() + self.width() - diff)) or # Right
        # Left-Top
        ((e_pos.y() < self.y() + diff) and # Top
        (e_pos.x() < self.x() + diff)) or # Left
        # Right-Top
        (e_pos.y() < self.y() + diff) and # Top
        (e_pos.x() > self.x() + self.width() - diff)): # Right
            # Left - Bottom
            if ((e_pos.y() > self.y() + self.height() - diff) and # Bottom
            (e_pos.x() < self.x()
                + diff)): # Left
                self.mode = Mode.RESIZEBL
                self.setCursor(QCursor(QtCore.Qt.SizeBDiagCursor))
                # Right - Bottom
            if ((e_pos.y() > self.y() + self.height() - diff) and # Bottom
            (e_pos.x() > self.x() + self.width() - diff)): # Right
                self.mode = Mode.RESIZEBR
                self.setCursor(QCursor(QtCore.Qt.SizeFDiagCursor))
            # Left - Top
            if ((e_pos.y() < self.y() + diff) and # Top
            (e_pos.x() < self.x() + diff)): # Left
                self.mode = Mode.RESIZETL
                self.setCursor(QCursor(QtCore.Qt.SizeFDiagCursor))
            # Right - Top
            if ((e_pos.y() < self.y() + diff) and # Top
            (e_pos.x() > self.x() + self.width() - diff)): # Right
                self.mode = Mode.RESIZETR
                self.setCursor(QCursor(QtCore.Qt.SizeBDiagCursor))
        # check cursor horizontal position
        elif ((e_pos.x() < self.x() + diff) or # Left
            (e_pos.x() > self.x() + self.width() - diff)): # Right
            if e_pos.x() < self.x() + diff: # Left
                self.setCursor(QCursor(QtCore.Qt.SizeHorCursor))
                self.mode = Mode.RESIZEL
            else: # Right
                self.setCursor(QCursor(QtCore.Qt.SizeHorCursor))
                self.mode = Mode.RESIZER
        # check cursor vertical position
        elif ((e_pos.y() > self.y() + self.height() - diff) or # Bottom
            (e_pos.y() < self.y() + diff)): # Top
            if e_pos.y() < self.y() + diff: # Top
                self.setCursor(QCursor(QtCore.Qt.SizeVerCursor))
                self.mode = Mode.RESIZET
            else: # Bottom
                self.setCursor(QCursor(QtCore.Qt.SizeVerCursor))
                self.mode = Mode.RESIZEB
        else:
            self.setCursor(QCursor(QtCore.Qt. ArrowCursor))
            self.mode = Mode.MOVE


    def mouseReleaseEvent(self, e: QtGui.QMouseEvent):
        QWidget.mouseReleaseEvent(self, e)


    def mouseMoveEvent(self, e: QtGui.QMouseEvent):
        QWidget.mouseMoveEvent(self, e)
        if not self.m_isEditing:
            return
        if not self.m_infocus:
            return
        if not e.buttons() and QtCore.Qt.LeftButton:
            p = QPoint(e.x() + self.geometry().x(), e.y() + self.geometry().y())
            self.setCursorShape(p)
            return

        if (self.mode == Mode.MOVE or self.mode == Mode.NONE) and e.buttons() and QtCore.Qt.LeftButton:
            toMove = e.globalPos() - self.position
            if toMove.x() < 0:return
            if toMove.y() < 0:return
            if toMove.x() > self.parentWidget().width() - self.width(): return
            self.move(toMove)
            self.newGeometry.emit(self.geometry())
            self.parentWidget().repaint()
            return
        if (self.mode != Mode.MOVE) and e.buttons() and QtCore.Qt.LeftButton:
            if self.mode == Mode.RESIZETL: # Left - Top
                newwidth = e.globalX() - self.position.x() - self.geometry().x()
                newheight = e.globalY() - self.position.y() - self.geometry().y()
                toMove = e.globalPos() - self.position
                self.resize(self.geometry().width() - newwidth, self.geometry().height() - newheight)
                self.move(toMove.x(), toMove.y())
            elif self.mode == Mode.RESIZETR: # Right - Top
                newheight = e.globalY() - self.position.y() - self.geometry().y()
                toMove = e.globalPos() - self.position
                self.resize(e.x(), self.geometry().height() - newheight)
                self.move(self.x(), toMove.y())
            elif self.mode== Mode.RESIZEBL: # Left - Bottom
                newwidth = e.globalX() - self.position.x() - self.geometry().x()
                toMove = e.globalPos() - self.position
                self.resize(self.geometry().width() - newwidth, e.y())
                self.move(toMove.x(), self.y())
            elif self.mode == Mode.RESIZEB: # Bottom
                self.resize(self.width(), e.y())
            elif self.mode == Mode.RESIZEL: # Left
                newwidth = e.globalX() - self.position.x() - self.geometry().x()
                toMove = e.globalPos() - self.position
                self.resize(self.geometry().width() - newwidth, self.height())
                self.move(toMove.x(), self.y())
            elif self.mode == Mode.RESIZET:# Top
                newheight = e.globalY() - self.position.y() - self.geometry().y()
                toMove = e.globalPos() - self.position
                self.resize(self.width(), self.geometry().height() - newheight)
                self.move(self.x(), toMove.y())
            elif self.mode == Mode.RESIZER: # Right
                self.resize(e.x(), self.height())
            elif self.mode == Mode.RESIZEBR:# Right - Bottom
                self.resize(e.x(), e.y())
            self.parentWidget().repaint()
        self.newGeometry.emit(self.geometry())
Esempio n. 43
0
    def createCurveIcons(self):
        pix = QPixmap(self.m_iconSize)
        painter = QPainter()

        gradient = QLinearGradient(0, 0, 0, self.m_iconSize.height())
        gradient.setColorAt(0.0, QColor(240, 240, 240))
        gradient.setColorAt(1.0, QColor(224, 224, 224))

        brush = QBrush(gradient)

        # The original C++ code uses undocumented calls to get the names of the
        # different curve types.  We do the Python equivalant (but without
        # cheating).
        curve_types = [(n, c) for n, c in QEasingCurve.__dict__.items()
                if isinstance(c, QEasingCurve.Type) and c != QEasingCurve.Custom]
        curve_types.sort(key=lambda ct: ct[1])

        painter.begin(pix)

        for curve_name, curve_type in curve_types:
            painter.fillRect(QRect(QPoint(0, 0), self.m_iconSize), brush)

            curve = QEasingCurve(curve_type)

            if curve_type == QEasingCurve.BezierSpline:
                curve.addCubicBezierSegment(QPointF(0.4, 0.1),
                        QPointF(0.6, 0.9), QPointF(1.0, 1.0))
            elif curve_type == QEasingCurve.TCBSpline:
                curve.addTCBSegment(QPointF(0.0, 0.0), 0, 0, 0)
                curve.addTCBSegment(QPointF(0.3, 0.4), 0.2, 1, -0.2)
                curve.addTCBSegment(QPointF(0.7, 0.6), -0.2, 1, 0.2)
                curve.addTCBSegment(QPointF(1.0, 1.0), 0, 0, 0)

            painter.setPen(QColor(0, 0, 255, 64))
            xAxis = self.m_iconSize.height() / 1.5
            yAxis = self.m_iconSize.width() / 3.0
            painter.drawLine(0, xAxis, self.m_iconSize.width(),  xAxis)
            painter.drawLine(yAxis, 0, yAxis, self.m_iconSize.height())

            curveScale = self.m_iconSize.height() / 2.0;

            painter.setPen(Qt.NoPen)

            # Start point.
            painter.setBrush(Qt.red)
            start = QPoint(yAxis,
                    xAxis - curveScale * curve.valueForProgress(0))
            painter.drawRect(start.x() - 1, start.y() - 1, 3, 3)

            # End point.
            painter.setBrush(Qt.blue)
            end = QPoint(yAxis + curveScale,
                    xAxis - curveScale * curve.valueForProgress(1))
            painter.drawRect(end.x() - 1, end.y() - 1, 3, 3)

            curvePath = QPainterPath()
            curvePath.moveTo(QPointF(start))
            t = 0.0
            while t <= 1.0:
                to = QPointF(yAxis + curveScale * t,
                        xAxis - curveScale * curve.valueForProgress(t))
                curvePath.lineTo(to)
                t += 1.0 / curveScale

            painter.setRenderHint(QPainter.Antialiasing, True)
            painter.strokePath(curvePath, QColor(32, 32, 32))
            painter.setRenderHint(QPainter.Antialiasing, False)

            item = QListWidgetItem()
            item.setIcon(QIcon(pix))
            item.setText(curve_name)
            self.m_ui.easingCurvePicker.addItem(item)

        painter.end()
Esempio n. 44
0
class adamGLWidget(QOpenGLWidget):
    xRotationChanged = pyqtSignal(int)
    yRotationChanged = pyqtSignal(int)
    zRotationChanged = pyqtSignal(int)
    xTransChanged = pyqtSignal(int)
    yTransChanged = pyqtSignal(int)
    zTransChanged = pyqtSignal(int)

    def __init__(self, parent=None):
        super(adamGLWidget, self).__init__(parent)

        self.xRot = 0
        self.yRot = 0
        self.zRot = 0
        self.z_trans = 300
        self.x_trans = 0
        self.y_trans = 0
        self.z_near = 1.0
        self.z_far = 5000.

        self.cPart = 0

        self.g_ambientLight = (0.35, 0.35, 0.35, 1.0)
        self.g_diffuseLight = (0.75, 0.75, 0.75, 0.7)
        self.g_specular = (1.0, 1.0, 1.0, 1.0)

        self.lastPos = QPoint()
        self.render_lock = QMutex()
        #

    def load_adam(self, pkl_path):
        self.adamWrapper = ADAM(
            pkl_path=
            '/home/xiul/workspace/PanopticDome/models/adamModel_lbs_200.pkl')

        adamdpPath = '/media/posefs3b/Users/xiu/PanopticDome/models/adam_to_uvi.pkl'
        with open(adamdpPath) as fio:
            adamdpPkl = pickle.load(fio)

        dp_colors_adam = np.array(adamdpPkl['adam_to_uvi'])
        dp_colors_adam = dp_colors_adam[:, [1, 0, 2]]
        self.part_index = dp_colors_adam[:, 2].astype(np.int)
        self.dp_colors = dp_colors_adam
        self.dp_colors[:, 2] = self.dp_colors[:, 2] / 255.0
        self.dp_colors[:, :] = self.dp_colors[:, ::-1]

        self.dp_colors_shuffle = self.dp_colors.copy()
        np.random.shuffle(self.dp_colors_shuffle)

        self.dp_colors_shuffle[:, 0] = self.dp_colors_shuffle[:, 0] / 24 * 200
        #self.dp_colors[:,0:2] = 0.5

        self.f = self.adamWrapper.f
        vshape = self.adamWrapper.size[0]

        vbyf_vid = self.f.flatten('F')
        vbyf_fid = np.arange(self.f.shape[0])
        vbyf_fid = np.concatenate((vbyf_fid, vbyf_fid, vbyf_fid))
        vbyf_val = np.ones(len(vbyf_vid))
        self.vbyf = scipy.sparse.coo_matrix(
            (vbyf_val, (vbyf_vid, vbyf_fid)),
            shape=(vshape, self.f.shape[0])).tocsr()

        pose = np.zeros(186)
        trans = np.zeros(3)
        betas = np.zeros(30)
        exps = np.zeros(200)
        self.adamJoints = None
        self.adamParam = {
            "pose": pose,
            "trans": trans,
            "betas": betas,
            "faces": exps
        }

        self.instanceAdam()

    def getOpenglInfo(self):
        info = """
            Vendor: {}
            Renderer: {}
            OpenGL Version: {}
            Shader Version: {}
        """.format(glGetString(GL_VENDOR), glGetString(GL_RENDERER),
                   glGetString(GL_VERSION),
                   glGetString(GL_SHADING_LANGUAGE_VERSION))
        return info

    def vertices_normals(self, f, v):

        fNormal_u = v[f[:, 1], :] - v[f[:, 0], :]
        fNormal_v = v[f[:, 2], :] - v[f[:, 0], :]
        fNormal = np.cross(fNormal_u, fNormal_v)
        fNormal = sklearn.preprocessing.normalize(fNormal)
        vNormal = self.vbyf.dot(fNormal)
        vNormal = sklearn.preprocessing.normalize(vNormal)
        return vNormal

    def instanceAdam(self):
        self.render_lock.lock()
        adamParam = self.adamParam
        adamParam['faces'] = numpy.random.random_sample((200, )) / 80
        trans = adamParam['trans'][np.newaxis, :]
        betas = adamParam['betas'][np.newaxis, :]
        poses = adamParam['pose'][np.newaxis, :]
        exps = adamParam['faces'][np.newaxis, :]

        v, j = self.adamWrapper(betas, poses, exps, get_skin=True)
        v += np.expand_dims(trans, axis=1)
        #j += np.expand_dims(trans, axis=1)
        j += trans

        self.adamJoints = j[0, :, :]

        import copy
        c = copy.deepcopy(self.dp_colors_shuffle)
        if self.cPart > 0:
            cHi = self.part_index != self.cPart
            c[cHi, :] = [0.5, 0.5, 0.5]

        c_data = c.flatten()

        v = np.reshape(v, (-1, 3))

        vn = self.vertices_normals(f=self.f, v=v)

        v_data = v.flatten()
        vn_data = vn.flatten()

        glBindBuffer(GL_ARRAY_BUFFER, self.vn_buffer)
        glBufferData(GL_ARRAY_BUFFER,
                     len(vn_data) * sizeof(ctypes.c_float),
                     (ctypes.c_float * len(vn_data))(*vn_data), GL_STATIC_DRAW)
        glBindBuffer(GL_ARRAY_BUFFER, self.vts_buffer)
        glBufferData(GL_ARRAY_BUFFER,
                     len(v_data) * sizeof(ctypes.c_float),
                     (ctypes.c_float * len(v_data))(*v_data), GL_STATIC_DRAW)
        glBindBuffer(GL_ARRAY_BUFFER, self.color_buffer)
        glBufferData(GL_ARRAY_BUFFER,
                     len(c_data) * sizeof(ctypes.c_float),
                     (ctypes.c_float * len(c_data))(*c_data), GL_STATIC_DRAW)
        self.render_lock.unlock()

    def renderAdam(self):
        self.render_lock.lock()
        smpl_color = [125 / 255.0, 125 / 255.0, 125 / 255.0]
        glPushMatrix()
        glShadeModel(GL_SMOOTH)
        #glEnable(GL_LIGHTING)
        glColor4f(smpl_color[0], smpl_color[1], smpl_color[2], 0.3)
        ambientFskeleton = 0.1
        diffuseFskeleton = 0.9
        specularFskeleton = 0.1
        smpl_shiness = 120.0
        smpl_ambient = [
            ambientFskeleton * smpl_color[0], ambientFskeleton * smpl_color[1],
            ambientFskeleton * smpl_color[2], 1.0
        ]
        smpl_diffuse = [
            diffuseFskeleton * smpl_color[0], diffuseFskeleton * smpl_color[1],
            diffuseFskeleton * smpl_color[2], 1.0
        ]
        smpl_spectular = [
            specularFskeleton * smpl_color[0],
            specularFskeleton * smpl_color[1],
            specularFskeleton * smpl_color[2], 1.0
        ]
        glMaterialfv(GL_FRONT, GL_AMBIENT, smpl_ambient)
        glMaterialfv(GL_FRONT, GL_DIFFUSE, smpl_diffuse)
        glMaterialfv(GL_FRONT, GL_SPECULAR, smpl_spectular)
        glMaterialf(GL_FRONT, GL_SHININESS, smpl_shiness)
        glLineWidth(.5)
        if not self.cPart == 1:
            glEnableVertexAttribArray(2)
            glBindBuffer(GL_ARRAY_BUFFER, self.vn_buffer)
            glVertexAttribPointer(
                2,  # attribute
                3,  # size
                GL_FLOAT,  # type
                GL_TRUE,  # normalized?
                0,  #/ stride
                None  # array buffer offset
            )
            glEnableVertexAttribArray(0)
            glBindBuffer(GL_ARRAY_BUFFER, self.vts_buffer)
            glVertexAttribPointer(
                0,  # attribute
                3,  # size
                GL_FLOAT,  # type
                GL_FALSE,  # normalized?
                0,  #/ stride
                None  # array buffer offset
            )

            glEnableVertexAttribArray(3)
            glBindBuffer(GL_ARRAY_BUFFER, self.color_buffer)
            glVertexAttribPointer(
                3,  # attribute
                3,  # size
                GL_FLOAT,  # type
                GL_FALSE,  # normalized?
                0,  #/ stride
                None  # array buffer offset
            )

            glPolygonMode(GL_FRONT, GL_FILL)
            glPolygonMode(GL_BACK, GL_FILL)
            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.inds_buffer)
            glDrawElements(GL_TRIANGLES, self.f.shape[0] * 3, GL_UNSIGNED_INT,
                           None)
            glPolygonMode(GL_FRONT, GL_FILL)
            glPolygonMode(GL_BACK, GL_FILL)
        else:
            np.savetxt('Adam.txt', self.adamJoints)

        glPopMatrix()

        #render Joints
        for cid, pid in enumerate(self.adamWrapper.parents):
            if pid >= 0:
                # glColor4f(1.0,0.0,0.0,1.0)
                # glBegin(GL_LINES)
                # glVertex3f(self.adamJoints[cid,0],self.adamJoints[cid,1],self.adamJoints[cid,2])
                # glVertex3f(self.adamJoints[pid,0],self.adamJoints[pid,1],self.adamJoints[pid,2])
                # glEnd()
                glLineWidth(1)
                glColor4f(1.0, 0.0, 0.0, 1.0)
                glBegin(GL_LINES)
                #self.easyCylinder(self.adamJoints[cid],self.adamJoints[pid],15,[1.0,0.0,1.0,1])
                glVertex3f(self.adamJoints[cid, 0], self.adamJoints[cid, 1],
                           self.adamJoints[cid, 2])
                glVertex3f(self.adamJoints[pid, 0], self.adamJoints[pid, 1],
                           self.adamJoints[pid, 2])
                glEnd()

                glPointSize(5)
                glBegin(GL_POINTS)

                glColor4f(0.1, 0.0, 1.0, 1.0)
                glVertex3f(self.adamJoints[cid, 0], self.adamJoints[cid, 1],
                           self.adamJoints[cid, 2])
                glEnd()

        self.render_lock.unlock()

    def setColorPart(self, partid):
        self.cPart = partid
        self.instanceAdam()
        self.update()

    def setAdamPoseParam(self, adamPose):
        self.adamParam['pose'] = adamPose
        self.instanceAdam()
        self.update()

    def setXRotation(self, angle):
        angle = self.normalizeAngle(angle)
        if angle != self.xRot:
            self.xRot = angle
            self.xRotationChanged.emit(angle)
            self.update()

    def setYRotation(self, angle):
        angle = self.normalizeAngle(angle)
        if angle != self.yRot:
            self.yRot = angle
            self.yRotationChanged.emit(angle)
            self.update()

    def setZRotation(self, angle):
        angle = self.normalizeAngle(angle)
        if angle != self.zRot:
            self.zRot = angle
            self.zRotationChanged.emit(angle)
            self.update()

    def setXTrans(self, trans):
        if trans != self.x_trans:
            self.x_trans = trans
            self.xTransChanged.emit(trans)
            self.update()

    def setYTrans(self, trans):
        if trans != self.y_trans:
            self.y_trans = trans
            self.yTransChanged.emit(trans)
            self.update()

    def setZTrans(self, trans):
        if trans != self.z_trans:
            self.z_trans = trans
            self.zTransChanged.emit(trans)
            self.update()

    def initializeGL(self):
        print(self.getOpenglInfo())

        self.vts_buffer = glGenBuffers(1)
        self.vn_buffer = glGenBuffers(1)
        self.inds_buffer = glGenBuffers(1)
        self.color_buffer = glGenBuffers(1)

        self.load_adam(
            '/home/xiul/workspace/PanopticDome/models/adamModel_lbs_200.pkl')
        f_data = self.f.flatten()
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.inds_buffer)
        glBufferData(GL_ELEMENT_ARRAY_BUFFER,
                     sizeof(ctypes.c_uint) * len(f_data),
                     (ctypes.c_uint * len(f_data))(*f_data), GL_STATIC_DRAW)
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)

        glClearColor(1.0, 1.0, 1.0, 1.0)
        # Enable depth testing
        #glShadeModel(GL_SMOOTH)

        glShadeModel(GL_FLAT)
        glProvokingVertex(GL_FIRST_VERTEX_CONVENTION)
        glLightfv(GL_LIGHT0, GL_AMBIENT, self.g_ambientLight)
        glLightfv(GL_LIGHT0, GL_DIFFUSE, self.g_diffuseLight)
        glLightfv(GL_LIGHT0, GL_SPECULAR, self.g_specular)
        glLightfv(GL_LIGHT0, GL_POSITION, [-1, -1, 0])
        # glEnable(GL_LIGHTING)
        glDisable(GL_LIGHTING)
        glEnable(GL_LIGHT0)
        glEnable(GL_DEPTH_TEST)
        glEnable(GL_COLOR_MATERIAL)
        glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE)

        #gen buffer

    def paintGL(self):
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        glLoadIdentity()
        gluLookAt(0, 0, 0, 0, 0, 1, 0, -1, 0)
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()

        gluPerspective(65,
                       float(self.width()) / float(self.height()), self.z_near,
                       self.z_far)
        glMatrixMode(GL_MODELVIEW)

        self.setView()
        #self.renderFloor()
        self.renderAdam()

    def resizeGL(self, width, height):
        glViewport(0, 0, width, height)

    def mousePressEvent(self, event):
        self.lastPos = event.pos()

    def mouseMoveEvent(self, event):
        dx = event.x() - self.lastPos.x()
        dy = event.y() - self.lastPos.y()

        if event.buttons() & Qt.LeftButton:
            self.setXRotation(self.xRot + 2 * dy)
            self.setYRotation(self.yRot + 2 * dx)
        # elif event.buttons() & Qt.RightButton:
        #     self.setXTrans(self.x_trans+8*dx)
        #     self.setYTrans(self.y_trans+8*dy)
        self.lastPos = event.pos()

    def wheelEvent(self, event):
        dz = event.angleDelta().y() / 8
        self.setZTrans(self.z_trans + dz)

    def normalizeAngle(self, angle):
        while angle < 0:
            angle += 360
        while angle > 360:
            angle -= 360
        return angle

    def setClearColor(self, c):
        glClearColor(c.redF(), c.greenF(), c.blueF(), c.alphaF())

    def setColor(self, c):
        glColor4f(c.redF(), c.greenF(), c.blueF(), c.alphaF())

    def renderFloor(self):
        gridNum = 10
        width = 50
        g_floorCenter = np.array([0, 0, 0])
        g_floorAxis1 = np.array([1, 0, 0])
        g_floorAxis2 = np.array([0, 0, 1])
        origin = g_floorCenter - g_floorAxis1 * \
            (width*gridNum/2) - g_floorAxis2*(width*gridNum/2)
        axis1 = g_floorAxis1 * width
        axis2 = g_floorAxis2 * width
        for y in range(gridNum + 1):
            for x in range(gridNum + 1):
                if (x + y) % 2 == 0:
                    glColor(1.0, 1.0, 1.0, 1.0)  # white
                else:
                    glColor(0.7, 0.7, 0.7, 1)  # grey
                p1 = origin + axis1 * x + axis2 * y
                p2 = p1 + axis1
                p3 = p1 + axis2
                p4 = p1 + axis1 + axis2
                glBegin(GL_QUADS)
                glVertex3f(p1[0], p1[1], p1[2])
                glVertex3f(p2[0], p2[1], p2[2])
                glVertex3f(p4[0], p4[1], p4[2])
                glVertex3f(p3[0], p3[1], p3[2])
                glEnd()

    def setView(self):
        glTranslatef(0, 0, self.z_trans)
        glRotatef(self.xRot, 1.0, 0.0, 0.0)
        glRotatef(self.yRot, 0.0, 1.0, 0.0)
        glRotatef(self.zRot, 0.0, 0.0, 1.0)
        glTranslatef(self.x_trans, 0.0, 0.0)
        glTranslatef(0.0, self.y_trans, 0.0)
Esempio n. 45
0
 def move(self, pos):
     # make new pos to center
     pos = QPoint(pos.x() - self.width() * 0.5, pos.y() - self.height() * 0.5)
     # make this always on top
     self.raise_()
     QWidget.move(self, pos)
Esempio n. 46
0
class GLWidget(QGLWidget):
    def __init__(self, parent=None):
        super(GLWidget, self).__init__(parent)

        self.object = 0
        self.xRot = 0
        self.yRot = 0
        self.zRot = 0

        self.lastPos = QPoint()

        # 设置QT图形颜色,静态函数fromRgb(), fromHsv(),fromCmyk()可以通过指定特定值返回需要的颜色
        # CYMK:青色Cyan、洋红色Magenta、黄色Yellow,黑色Black
        self.trolltechGreen = QColor.fromCmykF(0.50, 0.50, 0.1, 0.0)
        # 设置界面背景色
        self.trolltechPurple = QColor.fromCmykF(0.39, 0.39, 0.39, 0.0)

    def minimumSizeHint(self):
        # QSize 类代表一个矩形区域的大小,实现在 QtCore 共享库中。它可以认为是由一个整型的宽度和整型的高度组合
        return QSize(50, 50)

    def sizeHint(self):
        return QSize(400, 400)

    def normalizeAngle(self, angle):
        print('angle=', angle)
        if angle < 0:
            angle += 360 * 16
        elif angle > 360 * 16:
            angle -= 360 * 16
        else:
            pass
        return angle

    def setXRotation(self, angle):
        angle = self.normalizeAngle(angle)
        if angle != self.xRot:
            self.xRot = angle
            self.update()
            # 也可以是self.updateGL()

    def setYRotation(self, angle):
        angle = self.normalizeAngle(angle)
        if angle != self.yRot:
            self.yRot = angle
            self.update()
            # 也可以是self.updateGL()

    def setZRotation(self, angle):
        angle = self.normalizeAngle(angle)
        if angle != self.zRot:
            self.zRot = angle
            self.update()
            # 也可以是self.updateGL()

    # mousePressEvent鼠标键按下时调用
    def mousePressEvent(self, event):
        # pos() - 返回相对于控件空间的QPoint对象;
        self.lastPos = event.localPos()
        print('lastPos1.x = ', self.lastPos.x())
        print('lastPos1.y = ', self.lastPos.y())

    def mouseMoveEvent(self, event):
        # x() - 返回当前控件上鼠标的x坐标
        dx = +event.x() - self.lastPos.x()
        print('event.x=', event.x())
        dy = -event.y() + self.lastPos.y()
        print('event.y=', event.y())
        print('lastPos.x2 = ', self.lastPos.x())
        print('lastPos.y2 = ', self.lastPos.y())

        if event.buttons() == Qt.LeftButton:
            self.setXRotation(self.xRot + 8 * dy)
            self.setYRotation(self.yRot + 8 * dx)
        elif event.buttons() == Qt.RightButton:
            self.setXRotation(self.xRot + 8 * dy)
            self.setZRotation(self.zRot + 8 * dx)

        self.lastPos = event.pos()

    def initializeGL(self):
        self.qglClearColor(self.trolltechPurple.darker())
        self.object = self.makeObject()
        GL.glShadeModel(GL.GL_FLAT)
        GL.glEnable(GL.GL_DEPTH_TEST)
        GL.glEnable(GL.GL_CULL_FACE)

    def paintGL(self):
        '''
		clear buffers to preset values,用预制的值来清空缓冲区
		参数:
		GL_COLOR_BUFFER_BIT,颜色缓冲
		GL_DEPTH_BUFFER_BIT,深度缓冲
		GL_STENCIL_BUFFER_BIT,模板缓冲
		'''
        GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT)
        GL.glLoadIdentity()
        GL.glTranslated(0.0, 0.0, -6.0)

        # GL.glRotated函数功能:以点(0,0,0)到点(x,y,z)为轴,旋转angle角度;
        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.glCallList(self.object)

    def resizeGL(self, width, height):
        side = min(width, height)
        if side < 0:
            return
        '''
		Viewport(GLint x,GLint y,GLsizei width,GLsizei height)
		x,y 以像素为单位,指定了视口的左下角位置
		width,height 表示这个视口矩形的宽度和高度,根据窗口的实时变化重绘窗口。
		# //为向下取整
		'''

        GL.glViewport(0, 0, side, side)
        GL.glMatrixMode(GL.GL_PROJECTION)
        GL.glLoadIdentity()
        # 正交投影glOrtho(left, right, bottom, top, near, far)
        # 透视投影glFrustum(left, right, bottom, top, near, far)
        # glFrustum()中near和far表示离视点的远近,它们总为正值(near/far 必须>0)
        GL.glFrustum(-0.5, +0.5, +0.5, -0.5, 5.0, 8.0)
        GL.glMatrixMode(GL.GL_MODELVIEW)

    def makeObject(self):
        # glGenLists()会生成一组连续的空的显示列表,参数range为空列表数量
        genList = GL.glGenLists(1)
        GL.glNewList(genList, GL.GL_COMPILE)

        GL.glBegin(GL.GL_TRIANGLE_STRIP)
        r_sec = 0.02
        R_ring = 0.3

        NumRing = 120
        NumSec = 20
        delta_AR = 2 * math.pi / NumRing
        delta_AS = 2 * math.pi / NumSec
        AngleRing = 0
        for i in range(NumRing):
            AngleRing = AngleRing + delta_AR

            AngleSec = 0
            for j in range(NumSec + 1):

                x_p1 = (R_ring +
                        r_sec * math.cos(AngleSec)) * math.cos(AngleRing)
                y_p1 = (R_ring +
                        r_sec * math.cos(AngleSec)) * math.sin(AngleRing)
                z_p1 = r_sec * math.sin(AngleSec)

                x_p2 = (R_ring + r_sec *
                        math.cos(AngleSec)) * math.cos(AngleRing + delta_AR)
                y_p2 = (R_ring + r_sec *
                        math.cos(AngleSec)) * math.sin(AngleRing + delta_AR)
                z_p2 = r_sec * math.sin(AngleSec)

                GL.glColor3f(i / (NumRing), 0.5, 0.5)
                GL.glVertex3d(x_p1, y_p1, z_p1)
                GL.glVertex3d(x_p2, y_p2, z_p2)

                AngleSec = AngleSec + delta_AS

        trans_x = (R_ring - r_sec) * 2
        rotate_X = 15 * math.pi / 180

        GL.glEnd()
        GL.glEndList()
        return genList
Esempio n. 47
0
    class ScribbleArea(QWidget):
        def __init__(self, width, height, scaling_factor, foreground_color, background_color, enable_grid, grid_color, parent):
            super().__init__(parent)

            self.parent = parent
            self.scribbling = 0

            self.width = width
            self.height = height
            self.scaling_factor = scaling_factor
            self.pen_width = 1
            self.foreground_color = foreground_color
            self.background_color = background_color
            self.grid_enabled = enable_grid

            if grid_color is not None:
                self.grid_color = grid_color
            else:
                self.grid_color = self.palette().color(QPalette.Window)

            self.image = QImage(QSize(width, height), QImage.Format_RGB32)

            self.setFixedSize(width*self.scaling_factor, height*self.scaling_factor)
            self.last_point = QPoint()
            self.clear_image()

        def set_foreground_color(self, color):
            self.foreground_color = color

        def array_draw(self, r, g, b, scale=1):
            for i in range(len(r)):
                self.image.setPixel(QPoint(i%self.width, i//self.width), (r[i]*scale << 16) | (g[i]*scale << 8) | b[i]*scale)

            self.update()

        def fill_image(self, color):
            self.image.fill(color)
            self.update()

        def clear_image(self):
            self.image.fill(self.background_color)
            self.update()

        def mousePressEvent(self, event):
            self.parent.scribbling_started.emit()

            if event.button() == Qt.LeftButton:
                self.last_point = event.pos()
                self.scribbling = 1
            elif event.button() == Qt.RightButton:
                self.last_point = event.pos()
                self.scribbling = 2

        def mouseMoveEvent(self, event):
            if (event.buttons() & Qt.LeftButton) and self.scribbling == 1:
                self.draw_line_to(event.pos())
            elif (event.buttons() & Qt.RightButton) and self.scribbling == 2:
                self.draw_line_to(event.pos())

        def mouseReleaseEvent(self, event):
            if event.button() == Qt.LeftButton and self.scribbling == 1:
                self.draw_line_to(event.pos())
                self.scribbling = 0
            elif event.button() == Qt.RightButton and self.scribbling == 2:
                self.draw_line_to(event.pos())
                self.scribbling = 0

        def paintEvent(self, event):
            painter = QPainter(self)
            painter.drawImage(QRect(0, 0, super().width(), super().height()), self.image)

            if self.grid_enabled:
                painter.setPen(QPen(self.grid_color))

                for x in range(1, self.width):
                    painter.drawLine(x * self.scaling_factor, 0, x * self.scaling_factor, super().height())

                for y in range(1, self.height):
                    painter.drawLine(0, y * self.scaling_factor, super().width(), y * self.scaling_factor)

            self.parent.paint_overlay(event, painter)

        def draw_line_to(self, end_point):
            painter = QPainter(self.image)
            painter.setPen(QPen(self.foreground_color if self.scribbling == 1 else self.background_color,
                                self.pen_width, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))

            painter.drawLine(QPoint(self.last_point.x()//self.scaling_factor, self.last_point.y()//self.scaling_factor),
                             QPoint(end_point.x()//self.scaling_factor, end_point.y()//self.scaling_factor))

            self.update()
            self.last_point = QPoint(end_point)
Esempio n. 48
0
class GLWidget(QOpenGLWidget):
    xRotationChanged = pyqtSignal(int)
    yRotationChanged = pyqtSignal(int)
    zRotationChanged = pyqtSignal(int)

    def __init__(self, parent=None):
        super(GLWidget, self).__init__(parent)

        self.object = 0
        self.xRot = 0
        self.yRot = 0
        self.zRot = 0

        self.lastPos = QPoint()

        self.trolltechGreen = QColor.fromCmykF(0.40, 0.0, 1.0, 0.0)
        self.trolltechPurple = QColor.fromCmykF(0.39, 0.39, 0.0, 0.0)

    def minimumSizeHint(self):
        return QSize(50, 50)

    def sizeHint(self):
        return QSize(400, 400)

    def setXRotation(self, angle):
        angle = self.normalizeAngle(angle)
        if angle != self.xRot:
            self.xRot = angle
            self.xRotationChanged.emit(angle)
            self.update()

    def setYRotation(self, angle):
        angle = self.normalizeAngle(angle)
        if angle != self.yRot:
            self.yRot = angle
            self.yRotationChanged.emit(angle)
            self.update()

    def setZRotation(self, angle):
        angle = self.normalizeAngle(angle)
        if angle != self.zRot:
            self.zRot = angle
            self.zRotationChanged.emit(angle)
            self.update()

    def initializeGL(self):
        self.gl = self.context().versionFunctions()
        self.gl.initializeOpenGLFunctions()

        self.setClearColor(self.trolltechPurple.darker())
        self.object = self.makeObject()
        self.gl.glShadeModel(self.gl.GL_FLAT)
        self.gl.glEnable(self.gl.GL_DEPTH_TEST)
        self.gl.glEnable(self.gl.GL_CULL_FACE)

    def paintGL(self):
        self.gl.glClear(
                self.gl.GL_COLOR_BUFFER_BIT | self.gl.GL_DEPTH_BUFFER_BIT)
        self.gl.glLoadIdentity()
        self.gl.glTranslated(0.0, 0.0, -10.0)
        self.gl.glRotated(self.xRot / 16.0, 1.0, 0.0, 0.0)
        self.gl.glRotated(self.yRot / 16.0, 0.0, 1.0, 0.0)
        self.gl.glRotated(self.zRot / 16.0, 0.0, 0.0, 1.0)
        self.gl.glCallList(self.object)

    def resizeGL(self, width, height):
        side = min(width, height)
        if side < 0:
            return

        self.gl.glViewport((width - side) // 2, (height - side) // 2, side,
                side)

        self.gl.glMatrixMode(self.gl.GL_PROJECTION)
        self.gl.glLoadIdentity()
        self.gl.glOrtho(-0.5, +0.5, +0.5, -0.5, 4.0, 15.0)
        self.gl.glMatrixMode(self.gl.GL_MODELVIEW)

    def mousePressEvent(self, event):
        self.lastPos = event.pos()

    def mouseMoveEvent(self, event):
        dx = event.x() - self.lastPos.x()
        dy = event.y() - self.lastPos.y()

        if event.buttons() & Qt.LeftButton:
            self.setXRotation(self.xRot + 8 * dy)
            self.setYRotation(self.yRot + 8 * dx)
        elif event.buttons() & Qt.RightButton:
            self.setXRotation(self.xRot + 8 * dy)
            self.setZRotation(self.zRot + 8 * dx)

        self.lastPos = event.pos()

    def makeObject(self):
        genList = self.gl.glGenLists(1)
        self.gl.glNewList(genList, self.gl.GL_COMPILE)

        self.gl.glBegin(self.gl.GL_QUADS)

        x1 = +0.06
        y1 = -0.14
        x2 = +0.14
        y2 = -0.06
        x3 = +0.08
        y3 = +0.00
        x4 = +0.30
        y4 = +0.22

        self.quad(x1, y1, x2, y2, y2, x2, y1, x1)
        self.quad(x3, y3, x4, y4, y4, x4, y3, x3)

        self.extrude(x1, y1, x2, y2)
        self.extrude(x2, y2, y2, x2)
        self.extrude(y2, x2, y1, x1)
        self.extrude(y1, x1, x1, y1)
        self.extrude(x3, y3, x4, y4)
        self.extrude(x4, y4, y4, x4)
        self.extrude(y4, x4, y3, x3)

        NumSectors = 200

        for i in range(NumSectors):
            angle1 = (i * 2 * math.pi) / NumSectors
            x5 = 0.30 * math.sin(angle1)
            y5 = 0.30 * math.cos(angle1)
            x6 = 0.20 * math.sin(angle1)
            y6 = 0.20 * math.cos(angle1)

            angle2 = ((i + 1) * 2 * math.pi) / NumSectors
            x7 = 0.20 * math.sin(angle2)
            y7 = 0.20 * math.cos(angle2)
            x8 = 0.30 * math.sin(angle2)
            y8 = 0.30 * math.cos(angle2)

            self.quad(x5, y5, x6, y6, x7, y7, x8, y8)

            self.extrude(x6, y6, x7, y7)
            self.extrude(x8, y8, x5, y5)

        self.gl.glEnd()
        self.gl.glEndList()

        return genList

    def quad(self, x1, y1, x2, y2, x3, y3, x4, y4):
        self.setColor(self.trolltechGreen)

        self.gl.glVertex3d(x1, y1, -0.05)
        self.gl.glVertex3d(x2, y2, -0.05)
        self.gl.glVertex3d(x3, y3, -0.05)
        self.gl.glVertex3d(x4, y4, -0.05)

        self.gl.glVertex3d(x4, y4, +0.05)
        self.gl.glVertex3d(x3, y3, +0.05)
        self.gl.glVertex3d(x2, y2, +0.05)
        self.gl.glVertex3d(x1, y1, +0.05)

    def extrude(self, x1, y1, x2, y2):
        self.setColor(self.trolltechGreen.darker(250 + int(100 * x1)))

        self.gl.glVertex3d(x1, y1, +0.05)
        self.gl.glVertex3d(x2, y2, +0.05)
        self.gl.glVertex3d(x2, y2, -0.05)
        self.gl.glVertex3d(x1, y1, -0.05)

    def normalizeAngle(self, angle):
        while angle < 0:
            angle += 360 * 16
        while angle > 360 * 16:
            angle -= 360 * 16
        return angle

    def setClearColor(self, c):
        self.gl.glClearColor(c.redF(), c.greenF(), c.blueF(), c.alphaF())

    def setColor(self, c):
        self.gl.glColor4f(c.redF(), c.greenF(), c.blueF(), c.alphaF())
Esempio n. 49
0
class Settings(object):

    l = logging.getLogger('Settings')


    def __init__(self, fileName = 'notepad.ini'):
        self.fileName = fileName
        self.notepads = []
        self.mainWindowSize = QSize(1200, 700)
        self.mainWindowPos = QPoint(240, 200)
        self.browserPath = []

    
    def load(self):
        self.l.debug('Loading local settings ...')
        config = configparser.ConfigParser()
        config.read(self.fileName)

        # load dropbox configuration
        self.dropboxToken = ''
        if config.has_section('dropbox'):
            self.dropboxToken = config['dropbox'].get('dropboxToken')

        # load browser state
        if config.has_section('browser'):
            browserSettings = config['browser']
            path = browserSettings.get('path')
            self.browserPath = ast.literal_eval(path)

        # load main window position and size
        if config.has_section('mainWindow'):
            windowSettings = config['mainWindow']

            # read position
            pos = windowSettings.get('pos', '{},{}'.format(self.mainWindowPos.x(), self.mainWindowPos.y())).split(',')
            self.mainWindowPos = QPoint(int(pos[0]), int(pos[1]))

            # read size
            size = windowSettings.get('size', '{},{}'.format(self.mainWindowSize.width(), self.mainWindowSize.height())).split(',')
            self.mainWindowSize = QSize(int(size[0]), int(size[1]))

        # load notepads
        self.notepads = []
        for s in config.sections():
            if s.startswith('notepad_'):
                npDef = None
                npType = config.get(s, 'type')
                if npType == 'local':
                    npDef = {'name' : config.get(s, 'name'),
                             'type'  : npType,
                             'path'   : config.get(s, 'path') }
                elif npType == 'dropbox':
                    npDef = {'name' : config.get(s, 'name'),
                             'type'  : npType }
                if npDef is not None:
                    self.notepads.append(npDef)


    def dump(self, channel):
        self.l.debug('Saving local settings ...')
        config = configparser.ConfigParser()

        config.add_section('dropbox')
        config.set('dropbox', 'dropboxToken', self.dropboxToken)

        config.add_section('browser')
        config.set('browser', 'path', str(self.browserPath))

        config.add_section('mainWindow')
        config.set('mainWindow', 'pos', '{},{}'.format(self.mainWindowPos.x(), self.mainWindowPos.y()))
        config.set('mainWindow', 'size', '{},{}'.format(self.mainWindowSize.width(), self.mainWindowSize.height()))

        idx = 0
        for s in self.notepads:
            sectName = "notepad_{}".format(idx)
            idx += 1
            
            config.add_section(sectName)
            config.set(sectName, 'name', s['name'])
            config.set(sectName, 'type', s['type'])
            if s['type'] == 'local':
                config.set(sectName, 'path', s['path'])

        config.write(channel)

    
    def save(self):
        with open(self.fileName, 'w') as configfile:
            self.dump(configfile)


    def getNotepads(self):
        return self.notepads

    def addNotepad(self, npDef):
        self.notepads.append(npDef)

    def setMainWindowPos(self, pos):
        self.mainWindowPos = pos    

    def setBrowserPath(self, path):
        self.browserPath = path

    def setMainWindowSize(self, size):
        self.mainWindowSize = size

    def getMainWindowPos(self):
        return self.mainWindowPos

    def getMainWindowSize(self):
        return self.mainWindowSize

    def getBrowserPath(self):
        return self.browserPath

    def getDropboxToken(self):
        return self.dropboxToken 

    def setDropboxToken(self, token):
        self.dropboxToken = token 
Esempio n. 50
0
class GLWidget(QOpenGLWidget):
    xRotationChanged = pyqtSignal(int)
    yRotationChanged = pyqtSignal(int)
    zRotationChanged = pyqtSignal(int)

    def __init__(self, parent=None):
        super(GLWidget, self).__init__(parent)

        self.object = 0
        self.xRot = 0
        self.yRot = 0
        self.zRot = 0

        self.lastPos = QPoint()

        self.trolltechGreen = QColor.fromCmykF(0.40, 0.0, 1.0, 0.0)
        self.trolltechPurple = QColor.fromCmykF(0.39, 0.39, 0.0, 0.0)

    def minimumSizeHint(self):
        return QSize(50, 50)

    def sizeHint(self):
        return QSize(400, 400)

    def setXRotation(self, angle):
        angle = self.normalizeAngle(angle)
        if angle != self.xRot:
            self.xRot = angle
            self.xRotationChanged.emit(angle)
            self.update()

    def setYRotation(self, angle):
        angle = self.normalizeAngle(angle)
        if angle != self.yRot:
            self.yRot = angle
            self.yRotationChanged.emit(angle)
            self.update()

    def setZRotation(self, angle):
        angle = self.normalizeAngle(angle)
        if angle != self.zRot:
            self.zRot = angle
            self.zRotationChanged.emit(angle)
            self.update()

    def initializeGL(self):
        self.gl = self.context().versionFunctions()
        self.gl.initializeOpenGLFunctions()

        self.setClearColor(self.trolltechPurple.darker())
        self.object = self.makeObject()
        self.gl.glShadeModel(self.gl.GL_FLAT)
        self.gl.glEnable(self.gl.GL_DEPTH_TEST)
        self.gl.glEnable(self.gl.GL_CULL_FACE)

    def paintGL(self):
        self.gl.glClear(self.gl.GL_COLOR_BUFFER_BIT
                        | self.gl.GL_DEPTH_BUFFER_BIT)
        self.gl.glLoadIdentity()
        self.gl.glTranslated(0.0, 0.0, -10.0)
        self.gl.glRotated(self.xRot / 16.0, 1.0, 0.0, 0.0)
        self.gl.glRotated(self.yRot / 16.0, 0.0, 1.0, 0.0)
        self.gl.glRotated(self.zRot / 16.0, 0.0, 0.0, 1.0)
        self.gl.glCallList(self.object)

    def resizeGL(self, width, height):
        side = min(width, height)
        if side < 0:
            return

        self.gl.glViewport((width - side) // 2, (height - side) // 2, side,
                           side)

        self.gl.glMatrixMode(self.gl.GL_PROJECTION)
        self.gl.glLoadIdentity()
        self.gl.glOrtho(-0.5, +0.5, +0.5, -0.5, 4.0, 15.0)
        self.gl.glMatrixMode(self.gl.GL_MODELVIEW)

    def mousePressEvent(self, event):
        self.lastPos = event.pos()

    def mouseMoveEvent(self, event):
        dx = event.x() - self.lastPos.x()
        dy = event.y() - self.lastPos.y()

        if event.buttons() & Qt.LeftButton:
            self.setXRotation(self.xRot + 8 * dy)
            self.setYRotation(self.yRot + 8 * dx)
        elif event.buttons() & Qt.RightButton:
            self.setXRotation(self.xRot + 8 * dy)
            self.setZRotation(self.zRot + 8 * dx)

        self.lastPos = event.pos()

    def makeObject(self):
        genList = self.gl.glGenLists(1)
        self.gl.glNewList(genList, self.gl.GL_COMPILE)

        self.gl.glBegin(self.gl.GL_QUADS)

        x1 = +0.06
        y1 = -0.14
        x2 = +0.14
        y2 = -0.06
        x3 = +0.08
        y3 = +0.00
        x4 = +0.30
        y4 = +0.22

        self.quad(x1, y1, x2, y2, y2, x2, y1, x1)
        self.quad(x3, y3, x4, y4, y4, x4, y3, x3)

        self.extrude(x1, y1, x2, y2)
        self.extrude(x2, y2, y2, x2)
        self.extrude(y2, x2, y1, x1)
        self.extrude(y1, x1, x1, y1)
        self.extrude(x3, y3, x4, y4)
        self.extrude(x4, y4, y4, x4)
        self.extrude(y4, x4, y3, x3)

        NumSectors = 200

        for i in range(NumSectors):
            angle1 = (i * 2 * math.pi) / NumSectors
            x5 = 0.30 * math.sin(angle1)
            y5 = 0.30 * math.cos(angle1)
            x6 = 0.20 * math.sin(angle1)
            y6 = 0.20 * math.cos(angle1)

            angle2 = ((i + 1) * 2 * math.pi) / NumSectors
            x7 = 0.20 * math.sin(angle2)
            y7 = 0.20 * math.cos(angle2)
            x8 = 0.30 * math.sin(angle2)
            y8 = 0.30 * math.cos(angle2)

            self.quad(x5, y5, x6, y6, x7, y7, x8, y8)

            self.extrude(x6, y6, x7, y7)
            self.extrude(x8, y8, x5, y5)

        self.gl.glEnd()
        self.gl.glEndList()

        return genList

    def quad(self, x1, y1, x2, y2, x3, y3, x4, y4):
        self.setColor(self.trolltechGreen)

        self.gl.glVertex3d(x1, y1, -0.05)
        self.gl.glVertex3d(x2, y2, -0.05)
        self.gl.glVertex3d(x3, y3, -0.05)
        self.gl.glVertex3d(x4, y4, -0.05)

        self.gl.glVertex3d(x4, y4, +0.05)
        self.gl.glVertex3d(x3, y3, +0.05)
        self.gl.glVertex3d(x2, y2, +0.05)
        self.gl.glVertex3d(x1, y1, +0.05)

    def extrude(self, x1, y1, x2, y2):
        self.setColor(self.trolltechGreen.darker(250 + int(100 * x1)))

        self.gl.glVertex3d(x1, y1, +0.05)
        self.gl.glVertex3d(x2, y2, +0.05)
        self.gl.glVertex3d(x2, y2, -0.05)
        self.gl.glVertex3d(x1, y1, -0.05)

    def normalizeAngle(self, angle):
        while angle < 0:
            angle += 360 * 16
        while angle > 360 * 16:
            angle -= 360 * 16
        return angle

    def setClearColor(self, c):
        self.gl.glClearColor(c.redF(), c.greenF(), c.blueF(), c.alphaF())

    def setColor(self, c):
        self.gl.glColor4f(c.redF(), c.greenF(), c.blueF(), c.alphaF())
Esempio n. 51
0
class MapWidget(QWidget):
    def __init__(self, mapper: MapReceiver, settings=None):
        QWidget.__init__(self)
        self.mapper = mapper
        self.tile_size = 256
        self.tile_drawn = []
        self.lat = 56.842963648401295
        self.lon = 60.6005859375
        self.zoom = 15
        self.delta = QPoint(0, 0)
        self.to_rerender = False
        self.load_settings(settings)
        self.trammer = TransportReceiver()
        self.drag_start = None
        self.current_pos = None

    def load_settings(self, settings):
        if settings is None:
            return
        self.lat = settings['lat']
        self.lon = settings['lon']

    def get_settings(self):
        return {
            'lat': self.lat,
            'lon': self.lon
        }

    def paintEvent(self, e):
        zoom = 15
        painter = QPainter()
        painter.begin(self)
        try:
            if self.to_rerender:
                self.rerender(painter)
            else:
                self.draw_tiles_from_corner(painter, self.lat, self.lon, zoom)
            self.draw_trams(painter)
        except Exception as e:
            print(e)
        painter.end()

    def draw_tiles_from_corner(self, painter: QPainter, x, y, zoom):
        geom = self.geometry()
        corner_x, corner_y = self.mapper.coords_to_tile(x, y, zoom)
        row_number = 0
        for row in range(geom.top() - self.tile_size, geom.height(), self.tile_size):
            col_number = 0
            for column in range(geom.left() - self.tile_size, geom.right(), self.tile_size):
                target_rect = QRect(column, row, self.tile_size, self.tile_size)
                tile_rect = QRect(0, 0, self.tile_size, self.tile_size)
                res_x = corner_x + col_number
                res_y = corner_y + row_number
                tile = self.mapper.get_tile_from_numbers(res_x, res_y, zoom)
                tile.corner = target_rect.topLeft()
                self.tile_drawn.append(tile)
                painter.drawPixmap(target_rect, QPixmap(tile.path), tile_rect)
                tile.widget_x = target_rect.x()
                tile.widget_y = target_rect.y()
                col_number += 1
            row_number += 1

    def rerender(self, painter: QPainter):
        for tile in self.tile_drawn:
            tile.widget_x += self.delta.x()
            tile.widget_y += self.delta.y()
            target_rect = QRectF(tile.widget_x, tile.widget_y, self.tile_size, self.tile_size)
            tile_rect = QRectF(0, 0, self.tile_size, self.tile_size)
            painter.drawPixmap(target_rect, QPixmap(tile.path), tile_rect)
        self.fill_perimeter(painter)
        self.clear_tiles()

    def fill_perimeter(self, painter):
        self.fill_top_row(painter)
        self.fill_bottom_row(painter)
        self.fill_left_column(painter)
        self.fill_right_column(painter)

    def fill_top_row(self, painter: QPainter):
        top_tile = min(self.get_tiles_on_screen(), key=lambda tile: tile.widget_y)
        if top_tile.widget_y > -self.tile_size:
            row = top_tile.widget_y - self.tile_size
            col_number = 0
            res_row = top_tile.y - 1
            for column in range(int(top_tile.widget_x), self.geometry().width() + 1, self.tile_size):
                res_col = top_tile.x + col_number
                tile = self.mapper.get_tile_from_numbers(res_col, res_row, self.zoom)
                target_rect = QRectF(column, row, self.tile_size, self.tile_size)
                tile_rect = QRectF(0, 0, self.tile_size, self.tile_size)
                self.tile_drawn.append(tile)
                painter.drawPixmap(target_rect, QPixmap(tile.path), tile_rect)
                tile.widget_x = target_rect.x()
                tile.widget_y = target_rect.y()
                col_number += 1

    def fill_bottom_row(self, painter: QPainter):
        bottom_tile = max(self.get_tiles_on_screen(), key=lambda cur_tile: cur_tile.widget_y)
        if bottom_tile.widget_y < self.geometry().height():
            row = bottom_tile.widget_y + self.tile_size
            col_number = 0
            res_row = bottom_tile.y + 1
            for column in range(int(bottom_tile.widget_x), self.geometry().width() + 1, self.tile_size):
                res_col = bottom_tile.x + col_number
                tile = self.mapper.get_tile_from_numbers(res_col, res_row, self.zoom)
                target_rect = QRectF(column, row, self.tile_size, self.tile_size)
                tile_rect = QRectF(0, 0, self.tile_size, self.tile_size)
                self.tile_drawn.append(tile)
                painter.drawPixmap(target_rect, QPixmap(tile.path), tile_rect)
                tile.widget_x = target_rect.x()
                tile.widget_y = target_rect.y()
                col_number += 1

    def fill_left_column(self, painter: QPainter):
        left_tile = min(self.get_tiles_on_screen(), key=lambda tile: tile.widget_x)
        if left_tile.widget_x > -self.tile_size:
            column = left_tile.widget_x - self.tile_size
            row_number = 0
            res_col = left_tile.x - 1
            for row in range(int(left_tile.widget_y), self.geometry().height() + 1, self.tile_size):
                res_row = left_tile.y + row_number
                tile = self.mapper.get_tile_from_numbers(res_col, res_row, self.zoom)
                target_rect = QRectF(column, row, self.tile_size, self.tile_size)
                tile_rect = QRectF(0, 0, self.tile_size, self.tile_size)
                self.tile_drawn.append(tile)
                painter.drawPixmap(target_rect, QPixmap(tile.path), tile_rect)
                tile.widget_x = target_rect.x()
                tile.widget_y = target_rect.y()
                row_number += 1

    def fill_right_column(self, painter: QPainter):
        right_tile = max(self.get_tiles_on_screen(), key=lambda tile: tile.widget_x)
        if right_tile.widget_x < self.geometry().width() + 256:
            column = right_tile.widget_x + self.tile_size
            row_number = 0
            res_col = right_tile.x + 1
            for row in range(int(right_tile.widget_y), self.geometry().height() + 1, self.tile_size):
                res_row = right_tile.y + row_number
                tile = self.mapper.get_tile_from_numbers(res_col, res_row, self.zoom)
                target_rect = QRectF(column, row, self.tile_size, self.tile_size)
                tile_rect = QRectF(0, 0, self.tile_size, self.tile_size)
                self.tile_drawn.append(tile)
                painter.drawPixmap(target_rect, QPixmap(tile.path), tile_rect)
                tile.widget_x = target_rect.x()
                tile.widget_y = target_rect.y()
                row_number += 1

    def clear_tiles(self):
        geom = self.geometry()
        bounds = QRect(-self.tile_size, -self.tile_size, geom.width() + self.tile_size, geom.height() + self.tile_size)
        tiles = [tile for tile in self.tile_drawn if
                 self.fully_outside(QRect(tile.widget_x, tile.widget_y, self.tile_size, self.tile_size), bounds)]
        for tile in tiles:
            self.tile_drawn.remove(tile)

    def outside_bounds(self, rect: QRect, bounds: QRect):
        return rect.top() < bounds.top() or rect.bottom() > bounds.bottom() or rect.left() < bounds.left() or rect.right() > bounds.right()

    def fully_outside(self, rect: QRect, bounds: QRect):
        return rect.bottom() < bounds.top() or rect.right() < bounds.left() or rect.top() > bounds.bottom() or rect.left() > bounds.right()

    def get_tiles_on_screen(self):
        geom = self.geometry()
        return [tile for tile in self.tile_drawn if
                not self.outside_bounds(QRect(tile.widget_x, tile.widget_y, self.tile_size, self.tile_size),
                                        geom)]

    def point_is_outside(self, point: QPointF, bounds: QRectF):
        return point.x() < bounds.left() or point.x() > bounds.right() or point.y() < bounds.top() or point.y() > bounds.bottom()

    def draw_trams(self, painter: QPainter):
        trams = self.trammer.get_trams()
        last_tile = self.tile_drawn[-1]
        right_bottom = self.mapper.tile_too_coords(last_tile.x + 1, last_tile.y + 1, self.zoom)
        right_bottom = QPointF(right_bottom[1], right_bottom[0])
        width = math.fabs(right_bottom.x() - self.lon)
        height = math.fabs(right_bottom.y() - self.lat)
        bounds = QRectF(self.lon, right_bottom.y(), width, height)
        for tram in trams:
            location = QPointF(tram.lon, tram.lat)
            if self.point_is_outside(location, bounds):
                continue
            coords = self.count_tram_tile_coords(tram)
            if coords is not None:
                x, y = coords
                painter.setBrush(QColor(255, 0, 0))
                painter.drawEllipse(x, y, 10, 10)
                painter.drawText(x, y, tram.route)

    def count_tram_tile_coords(self, tram):
        tile = self.mapper.coords_to_tile(tram.lat, tram.lon, self.zoom)
        drawn_tile = self.find_tile(tile[0], tile[1])
        if drawn_tile is None:
            return
        tile_lat, tile_lon = self.mapper.tile_too_coords(tile[0], tile[1], self.zoom)
        dy = self.mapper.get_distance((tile_lat, tile_lon), (tram.lat, tile_lon))
        dx = self.mapper.get_distance((tile_lat, tile_lon), (tile_lat, tram.lon))
        resolution = self.mapper.get_resolution(tram.lat, self.zoom)
        tile_dy = dy / resolution
        tile_dx = dx / resolution
        return drawn_tile.widget_x + tile_dx, drawn_tile.widget_y + tile_dy

    def find_tile(self, x, y):
        for tile in self.tile_drawn:
            if tile.x == x and tile.y == y:
                return tile
        return None

    def find_tile_by_drawn_coords(self, x, y):
        for tile in self.tile_drawn:
            if x - tile.widget_x <= 256 and y - tile.widget_y <= 256:
                return tile
        return None

    def mousePressEvent(self, event):
        self.drag_start = event.localPos()

    def mouseMoveEvent(self, event):
        self.current_pos = event.localPos()
        tile = self.find_tile_by_drawn_coords(self.current_pos.x(), self.current_pos.y())
        if tile is None:
            return
        delta = self.current_pos - self.drag_start
        new_x, new_y = tile.x + delta.x() / 256, tile.y + delta.y() / 256
        new_lat, new_lon = self.mapper.tile_too_coords(new_x, new_y, self.zoom)
        old_lat, old_lon = self.mapper.tile_too_coords(tile.x, tile.y, self.zoom)
        coords_delta = (new_lat - old_lat, new_lon - old_lon)
        self.lat -= coords_delta[0]
        self.lon -= coords_delta[1]
        self.drag_start = self.current_pos
        self.delta = delta
        self.to_rerender = True
        self.update()
Esempio n. 52
0
class Window(QMainWindow):
    def __init__(self):
        super().__init__()

        top = 400
        left = 400
        width = 1200
        height = 500

        self.maximum_undo = 20

        self.obj_type = 'wall'
        self.obj_width = 10

        self.pix_per_meter = 10

        self.bgc = Qt.white

        self.shift_pressed = False

        icon = "icon.png"

        self.setGeometry(top, left, width, height)
        self.setWindowTitle("Map Designer")
        self.setWindowIcon(QIcon(icon))
        self.setFixedSize(width, height)

        self.hidden_obstacle_layer = QImage(1000, 500, QImage.Format_RGB32)
        self.hidden_obstacle_layer.fill(self.bgc)
        self.backup_hidden_obstacle = []
        self.backup_hidden_obstacle.append(self.hidden_obstacle_layer)
        self.temp_hidden_obstacle_layer = self.hidden_obstacle_layer

        self.hidden_railing_brush = QBrush(Qt.SolidPattern)
        self.hidden_railing_brush.setColor(Qt.red)
        self.hidden_wall_brush = QBrush(Qt.SolidPattern)
        self.hidden_wall_brush.setColor(Qt.black)
        self.hidden_pillar_brush = QBrush(Qt.SolidPattern)
        self.hidden_pillar_brush.setColor(Qt.green)
        self.hidden_counter_brush = QBrush(Qt.SolidPattern)
        self.hidden_counter_brush.setColor(Qt.blue)

        self.hidden_destination_layer = QImage(1000, 500, QImage.Format_RGB32)
        self.hidden_destination_layer.fill(self.bgc)
        self.backup_hidden_destination = []
        self.backup_hidden_destination.append(self.hidden_destination_layer)
        self.temp_hidden_destination_layer = self.hidden_destination_layer

        self.hidden_exit_brush = QBrush(Qt.SolidPattern)
        self.hidden_exit_brush.setColor(Qt.red)
        self.hidden_entry_brush = QBrush(Qt.SolidPattern)
        self.hidden_entry_brush.setColor(Qt.black)
        self.hidden_passage_brush = QBrush(Qt.SolidPattern)
        self.hidden_passage_brush.setColor(Qt.green)
        self.hidden_waiting_brush = QBrush(Qt.SolidPattern)
        self.hidden_waiting_brush.setColor(Qt.blue)

        self.hidden_pen = QPen()
        self.hidden_pen.setColor(self.bgc)

        self.left_layout = QHBoxLayout()
        self.left_zone = QWidget(self)
        self.left_zone.setLayout(self.left_layout)

        self.image = QImage(1000, 500, QImage.Format_RGB32)
        self.image.fill(self.bgc)

        self.image_label = QLabel(self)
        self.image_label.setGeometry(0, 0, 1000, 500)
        self.image_label.setPixmap(QPixmap.fromImage(self.image))

        self.left_layout.addWidget(self.image_label)
        self.left_layout.setSpacing(0)
        self.left_layout.setContentsMargins(0, 0, 0, 0)
        self.left_layout.setStretch(0, 0)
        self.left_layout.setGeometry(QRect(QPoint(0, 0), QPoint(1000, 500)))

        self.splitter = QSplitter(self)
        self.splitter.setOrientation(Qt.Horizontal)
        self.splitter.setContentsMargins(0, 0, 0, 0)
        self.splitter.setFixedSize(1200, 500)
        self.splitter.setHandleWidth(0)
        self.splitter.addWidget(self.left_zone)

        self.backup_image = []
        self.backup_image.append(self.image)

        self.draw_record = []

        self.temp_image = QImage(1000, 500, QImage.Format_RGB32)
        self.temp_image.fill(self.bgc)

        self.drawing = False

        self.lastPoint = QPoint()

        # mainMenu = self.menuBar()
        # mainMenu.setNativeMenuBar(False)
        # fileMenu = mainMenu.addMenu("File")
        # brushMenu = mainMenu.addMenu("Brush Size")
        # brushColor = mainMenu.addMenu("Brush Color")
        #
        # saveAction = QAction("Save", self)
        # saveAction.setShortcut("Ctrl+S")
        # fileMenu.addAction(saveAction)
        #
        # clearAction = QAction("Clear", self)
        # clearAction.setShortcut("Ctrl+C")
        # fileMenu.addAction(clearAction)
        #
        # px3Action = QAction("3px", self)
        # px3Action.setShortcut("Ctrl+3")
        # brushMenu.addAction(px3Action)
        #
        # px5Action = QAction("5px", self)
        # px5Action.setShortcut("Ctrl+5")
        # brushMenu.addAction(px5Action)
        #
        # px9Action = QAction("9px", self)
        # px9Action.setShortcut("Ctrl+9")
        # brushMenu.addAction(px5Action)
        #
        # blackAction = QAction("Black", self)
        # blackAction.setShortcut("Ctrl+B")
        # brushColor.addAction(blackAction)
        #
        # whiteAction = QAction("White", self)
        # whiteAction.setShortcut("Ctrl+W")
        # brushColor.addAction(whiteAction)

        # #按钮控件
        #
        # self.btn_obstacle = QPushButton(self)
        # self.btn_obstacle.setGeometry(1020, 40, 20, 20)
        # self.btn_obstacle.setText("■")
        # self.btn_obstacle.setStyleSheet("QPushButton{color: black; padding-bottom: 2px;}"
        # 								"QPushButton:hover{background-color: darkgrey}")
        #
        # self.btn_dest = QPushButton(self)
        # self.btn_dest.setGeometry(1020, 80, 20, 20)
        # self.btn_dest.setText("■")
        # self.btn_dest.setStyleSheet("color: green; padding-bottom: 2px")

        #绘制选项
        self.right_layout = QVBoxLayout()
        self.right_zone = QWidget(self)
        self.right_zone.setLayout(self.right_layout)
        self.splitter.addWidget(self.right_zone)
        #self.right_layout.addWidget(self.image_label)

        #0.坐标显示区
        self.right_layout.addStretch()
        self.coordinates_label = QLabel(self)
        self.coordinates_label.setText("当前坐标(m): ")
        self.coordinates_label.setFont(QFont("Noto Sans CJK SC"))
        self.right_layout.addWidget(self.coordinates_label)

        self.coordinates_disp = QLabel(self)
        self.coordinates_disp.setText("坐标: x =  0.0, \ty =  0.0")
        self.coordinates_disp.setFont(QFont("Noto Sans CJK SC"))
        self.right_layout.addWidget(self.coordinates_disp)

        #1. 绘制障碍物标题
        self.right_layout.addStretch()
        self.obstacle_label = QLabel(self)
        self.obstacle_label.setText("绘制障碍物: ")
        self.obstacle_label.setFont(QFont("Noto Sans CJK SC"))
        #self.obstacle_label.setGeometry(1010, 40, 100, 30)
        self.right_layout.addWidget(self.obstacle_label)

        self.obstacle_pen = QPen(Qt.SolidLine)
        self.obstacle_pen.setColor(Qt.black)

        #1.1 绘制护栏
        #1.1.1 护栏选择框
        self.select_railing = QRadioButton(self)
        self.select_railing.setText("护栏. ")
        self.select_railing.setFont(QFont("Noto Sans CJK SC"))
        self.select_railing.toggled.connect(self.drawTypeChange)
        self.right_layout.addWidget(self.select_railing)
        #self.select_railing.setGeometry(1030, 65, 60, 30)
        #1.1.2 护栏笔刷
        self.railing_brush = QBrush(Qt.BDiagPattern)
        self.railing_brush.setColor(Qt.darkGray)
        self.railing_width = 0.5

        # 1.2.1 墙体选择框
        self.wall_box = QHBoxLayout()
        self.select_wall = QRadioButton(self)
        self.select_wall.setText("墙体, ")
        self.select_wall.setFont(QFont("Noto Sans CJK SC"))
        self.select_wall.toggled.connect(self.drawTypeChange)
        #self.select_wall.setGeometry(1030, 90, 60, 30)
        self.wall_box.addWidget(self.select_wall)
        # 1.2.2 墙体笔刷
        self.wall_brush = QBrush(Qt.Dense6Pattern)
        self.wall_brush.setColor(Qt.darkGray)
        self.wall_width = 1
        #1.2.3 墙体宽度标签
        self.wall_width_label = QLabel(self)
        self.wall_width_label.setText("宽度(m): ")
        self.wall_width_label.setFont(QFont("Noto Sans CJK SC"))
        #self.wall_width_label.setGeometry(1090, 90, 60, 30)
        self.wall_box.addWidget(self.wall_width_label)
        # 1.2.3 墙体宽度输入框
        self.wall_width_input = QLineEdit(self)
        self.wall_width_input.setText("1")
        #self.wall_width_input.setGeometry(1140, 95, 30, 20)
        self.wall_width_input.setAlignment(Qt.AlignRight)
        self.wall_box.addWidget(self.wall_width_input)
        self.wall_width_input.textChanged.connect(self.widthChange)

        self.right_layout.addLayout(self.wall_box)

        # 1.3.1 立柱选择框
        self.pillar_box = QHBoxLayout()
        self.select_pillar = QRadioButton(self)
        self.select_pillar.setText("立柱, ")
        self.select_pillar.setFont(QFont("Noto Sans CJK SC"))
        self.select_pillar.toggled.connect(self.drawTypeChange)
        #self.select_pillar.setGeometry(1030, 90, 60, 30)
        self.pillar_box.addWidget(self.select_pillar)
        # 1.3.2 立柱笔刷
        self.pillar_brush = QBrush(Qt.Dense4Pattern)
        self.pillar_brush.setColor(Qt.darkGray)
        self.pillar_width = 1
        # 1.3.3 立柱宽度标签
        self.pillar_width_label = QLabel(self)
        self.pillar_width_label.setText("宽度(m): ")
        self.pillar_width_label.setFont(QFont("Noto Sans CJK SC"))
        # self.wall_width_label.setGeometry(1090, 90, 60, 30)
        self.pillar_box.addWidget(self.pillar_width_label)
        # 1.3.3 立柱宽度输入框
        self.pillar_width_input = QLineEdit(self)
        self.pillar_width_input.setText("1")
        # self.wall_width_input.setGeometry(1140, 95, 30, 20)
        self.pillar_width_input.setAlignment(Qt.AlignRight)
        self.pillar_box.addWidget(self.pillar_width_input)
        self.pillar_width_input.textChanged.connect(self.widthChange)

        self.right_layout.addLayout(self.pillar_box)

        # 1.4.1 柜台选择框
        #self.counter_box = QHBoxLayout()
        self.select_counter = QRadioButton(self)
        self.select_counter.setText("柜台. ")
        self.select_counter.setFont(QFont("Noto Sans CJK SC"))
        self.select_counter.toggled.connect(self.drawTypeChange)
        #self.select_counter.setGeometry(1030, 90, 60, 30)
        self.right_layout.addWidget(self.select_counter)
        #self.counter_box.addWidget(self.select_counter)
        # 1.4.2 柜台笔刷
        self.counter_brush = QBrush(Qt.HorPattern)
        self.counter_brush.setColor(Qt.darkGray)
        self.counter_width = 1
        # # 1.4.3 柜台宽度标签
        # self.counter_width_label = QLabel(self)
        # self.counter_width_label.setText("宽度(m): ")
        # self.counter_width_label.setFont(QFont("Noto Sans CJK SC"))
        # # self.wall_width_label.setGeometry(1090, 90, 60, 30)
        # self.counter_box.addWidget(self.counter_width_label)
        # # 1.4.3 柜台宽度输入框
        # self.counter_width_input = QLineEdit(self)
        # self.counter_width_input.setText("1")
        # # self.wall_width_input.setGeometry(1140, 95, 30, 20)
        # self.counter_width_input.setAlignment(Qt.AlignRight)
        # self.counter_box.addWidget(self.counter_width_input)
        # self.counter_width_input.textChanged.connect(self.widthChange)

        #self.right_layout.addLayout(self.counter_box)

        # 2. 绘制障碍物标题
        self.right_layout.addStretch()
        self.destination_label = QLabel(self)
        self.destination_label.setText("绘制出入口及休息区: ")
        self.destination_label.setFont(QFont("Noto Sans CJK SC"))
        # self.obstacle_label.setGeometry(1010, 40, 100, 30)
        self.right_layout.addWidget(self.destination_label)

        self.destination_pen = QPen(Qt.DashDotDotLine)
        self.destination_pen.setColor(Qt.lightGray)

        # 2.1 绘制出口
        # 2.1.1 出口选择框
        self.select_exit = QRadioButton(self)
        self.select_exit.setText("出口. ")
        self.select_exit.setFont(QFont("Noto Sans CJK SC"))
        self.select_exit.toggled.connect(self.drawTypeChange)
        self.right_layout.addWidget(self.select_exit)
        # self.select_railing.setGeometry(1030, 65, 60, 30)
        # 2.1.2 出口笔刷
        self.exit_brush = QBrush(Qt.BDiagPattern)
        color = QColor(0, 255, 0, 130)
        self.exit_brush.setColor(color)
        self.exit_width = 2

        # 2.2 绘制入口
        # 2.2.1 入口选择框
        self.select_entry = QRadioButton(self)
        self.select_entry.setText("入口. ")
        self.select_entry.setFont(QFont("Noto Sans CJK SC"))
        self.select_entry.toggled.connect(self.drawTypeChange)
        self.right_layout.addWidget(self.select_entry)
        # self.select_railing.setGeometry(1030, 65, 60, 30)
        # 2.2.2 入口笔刷
        self.entry_brush = QBrush(Qt.DiagCrossPattern)
        color = QColor(0, 255, 0, 130)
        self.entry_brush.setColor(color)
        self.entry_width = 2

        # 2.3 绘制出入口
        # 2.3.1 出入口选择框
        self.select_passage = QRadioButton(self)
        self.select_passage.setText("出入口. ")
        self.select_passage.setFont(QFont("Noto Sans CJK SC"))
        self.select_passage.toggled.connect(self.drawTypeChange)
        self.right_layout.addWidget(self.select_passage)
        # self.select_railing.setGeometry(1030, 65, 60, 30)
        # 2.3.2 出入口笔刷
        self.passage_brush = QBrush(Qt.Dense6Pattern)
        color = QColor(0, 255, 0, 120)
        self.passage_brush.setColor(color)
        self.passage_width = 2

        # 2.4 绘制休息区
        # 2.4.1 休息区选择框
        self.select_waiting = QRadioButton(self)
        self.select_waiting.setText("休息区. ")
        self.select_waiting.setFont(QFont("Noto Sans CJK SC"))
        self.select_waiting.toggled.connect(self.drawTypeChange)
        self.right_layout.addWidget(self.select_waiting)
        # self.select_railing.setGeometry(1030, 65, 60, 30)
        # 2.4.2 休息区笔刷
        self.waiting_brush = QBrush(Qt.SolidPattern)
        color = QColor(0, 255, 0, 25)
        self.waiting_brush.setColor(color)

        self.right_layout.addStretch()

        # 3. 保存图片按键
        self.save_button = QPushButton(self)
        self.save_button.setText("保存地图")
        self.save_button.setFont(QFont("Noto Sans CJK SC"))
        self.save_button.clicked.connect(self.saveMap)
        self.right_layout.addWidget(self.save_button)

        self.right_layout.addStretch()
        self.right_layout.addStretch()
        self.right_layout.addStretch()

        self.brush = self.railing_brush
        self.pen = self.obstacle_pen
        self.draw_type = "railing"
        self.width = self.railing_width

        self.setCentralWidget(self.splitter)

        self.setCentralWidget(self.splitter)

        self.splitter.setMouseTracking(True)
        self.setMouseTracking(True)
        self.image_label.setMouseTracking(True)
        self.image_label.installEventFilter(self)

        self.select_railing.setChecked(True)

        self.update()

    def saveMap(self):
        timenow = datetime.datetime.now()
        timestamp = datetime.datetime.strftime(timenow, '%Y-%m-%d_%H_%M_%S')

        filename = "./Maps/map_" + timestamp

        print(filename)
        pixmap = QPixmap.fromImage(self.image)
        pixmap.save(filename + "_map.bmp")

        pixmap1 = QPixmap.fromImage(self.hidden_obstacle_layer)
        pixmap1.save(filename + "_obs.bmp")

        pixmap2 = QPixmap.fromImage(self.hidden_destination_layer)
        pixmap2.save(filename + "_des.bmp")

    def widthChange(self):
        self.wall_width = int(self.wall_width_input.text())
        self.pillar_width = int(self.pillar_width_input.text())

    def drawTypeChange(self):
        if self.select_railing.isChecked():
            #print("railing")
            self.brush = self.railing_brush
            self.draw_type = "railing"
            self.width = self.railing_width
            self.pen = self.obstacle_pen
        elif self.select_wall.isChecked():
            #print("wall")
            self.brush = self.wall_brush
            self.draw_type = "wall"
            self.width = self.wall_width
            self.pen = self.obstacle_pen
        elif self.select_pillar.isChecked():
            #print("pillar")
            self.brush = self.pillar_brush
            self.draw_type = "pillar"
            self.width = self.pillar_width
            self.pen = self.obstacle_pen
        elif self.select_counter.isChecked():
            #print("counter")
            self.brush = self.counter_brush
            self.draw_type = "counter"
            self.width = self.counter_width
            self.pen = self.obstacle_pen
        elif self.select_exit.isChecked():
            # print("exit")
            self.brush = self.exit_brush
            self.draw_type = "exit"
            self.width = self.exit_width
            self.pen = self.destination_pen
        elif self.select_entry.isChecked():
            # print("entry")
            self.brush = self.entry_brush
            self.draw_type = "entry"
            self.width = self.entry_width
            self.pen = self.destination_pen
        elif self.select_passage.isChecked():
            # print("passage")
            self.brush = self.passage_brush
            self.draw_type = "passage"
            self.width = self.passage_width
            self.pen = self.destination_pen
        elif self.select_waiting.isChecked():
            # print("waiting")
            self.brush = self.waiting_brush
            self.draw_type = "waiting"
            self.pen = self.destination_pen

    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.drawing = True
            self.startPoint = event.pos()
            self.lastPoint = event.pos()
            self.temp_image = self.image.copy()

            if self.draw_type == "railing" or self.draw_type == "wall" or self.draw_type == "pillar" or self.draw_type == "counter":
                self.temp_hidden_obstacle_layer = self.hidden_obstacle_layer.copy(
                )
            else:
                self.temp_hidden_destination_layer = self.hidden_destination_layer.copy(
                )

            self.draw_record.insert(0, self.draw_type)
            if self.draw_record.__len__() > self.maximum_undo + 2:
                self.draw_record.pop()

            #print(self.startPoint)
            if self.draw_type == "pillar":
                self.image = self.temp_image.copy()
                painter = QPainter(self.image)
                painter.setPen(self.obstacle_pen)
                painter.setBrush(self.pillar_brush)
                start = QPoint(
                    self.startPoint.x() -
                    (self.pillar_width * self.pix_per_meter) / 2 - 1,
                    self.startPoint.y() -
                    (self.pillar_width * self.pix_per_meter) / 2 - 1)
                end = QPoint(
                    self.startPoint.x() +
                    (self.pillar_width * self.pix_per_meter) / 2 - 1,
                    self.startPoint.y() +
                    (self.pillar_width * self.pix_per_meter) / 2 - 1)
                rect = QRect(start, end)
                painter.drawEllipse(rect)

                self.backup_image.insert(0, self.image)
                if self.backup_image.__len__() > self.maximum_undo + 2:
                    self.backup_image.pop()

                ##
                self.hidden_obstacle_layer = self.temp_hidden_obstacle_layer.copy(
                )
                painter1 = QPainter(self.hidden_obstacle_layer)
                painter1.setPen(self.hidden_pen)
                painter1.setBrush(self.hidden_pillar_brush)
                painter1.drawEllipse(rect)

                self.backup_hidden_obstacle.insert(0,
                                                   self.hidden_obstacle_layer)
                if self.backup_hidden_obstacle.__len__(
                ) > self.maximum_undo + 2:
                    self.backup_hidden_obstacle.pop()

                self.drawing = False
                self.update()

    def eventFilter(self, Object, event):
        if event.type() == QEvent.MouseMove:
            x = event.x()
            y = event.y()
            if 0 <= x < 1000 and 0 <= y < 500:
                x = x / 10.0
                y = y / 10.0
                message = "坐标: x = " + str(float(
                    '%.1f' % x)) + ", \ty = " + str(float('%.1f' % y))
                self.coordinates_disp.setText(message)
        return QWidget.eventFilter(self, Object, event)

    def mouseMoveEvent(self, event):
        # x = event.x()
        # y = event.y()
        # #if 0 <= x < 1000 and 0 <= y < 500:
        # x = x / 10.0
        # y = y / 10.0
        # message = "坐标: x = " + str(float('%.1f' % x)) + ", y = " + str(float('%.1f' % y))
        # self.coordinates_disp.setText(message)

        if (event.buttons() and Qt.LeftButton) and self.drawing:
            self.lastPoint = event.pos()

            self.image = self.temp_image.copy()
            painter = QPainter(self.image)
            painter.setBrush(self.brush)
            painter.setPen(self.pen)

            if self.draw_type == "railing" or self.draw_type == "wall" or self.draw_type == "pillar" or self.draw_type == "counter":
                self.hidden_obstacle_layer = self.temp_hidden_obstacle_layer.copy(
                )
                painter1 = QPainter(self.hidden_obstacle_layer)
                if self.draw_type == "railing":
                    painter1.setBrush(self.hidden_railing_brush)
                elif self.draw_type == "wall":
                    painter1.setBrush(self.hidden_wall_brush)
                elif self.draw_type == "pillar":
                    painter1.setBrush(self.hidden_pillar_brush)
                elif self.draw_type == "counter":
                    painter1.setBrush(self.hidden_counter_brush)
                painter1.setPen(self.hidden_pen)
            else:
                self.hidden_destination_layer = self.temp_hidden_destination_layer.copy(
                )
                painter1 = QPainter(self.hidden_destination_layer)
                if self.draw_type == "exit":
                    painter1.setBrush(self.hidden_exit_brush)
                elif self.draw_type == "entry":
                    painter1.setBrush(self.hidden_entry_brush)
                elif self.draw_type == "passage":
                    painter1.setBrush(self.hidden_passage_brush)
                elif self.draw_type == "waiting":
                    painter1.setBrush(self.hidden_waiting_brush)
                painter1.setPen(self.hidden_pen)

            w = self.width * self.pix_per_meter

            startx = self.startPoint.x()
            starty = self.startPoint.y()
            endx = self.lastPoint.x()
            endy = self.lastPoint.y()

            if self.shift_pressed == False and self.draw_type != "waiting":
                degree, length = self.get_degree(self.startPoint,
                                                 self.lastPoint)

                painter.translate(self.startPoint)
                painter.rotate(degree)

                painter1.translate(self.startPoint)
                painter1.rotate(degree)

                start = QPoint(0, 0)
                end = QPoint(length, w)

                # if self.draw_type == "counter":
                # 	if abs(starty - endy) >= abs(startx - endx):
                # 		print("no shift, ver pattern")
                # 		temp_brush = self.brush
                # 		temp_brush.setStyle(Qt.HorPattern)
                # 		painter.setBrush(temp_brush)
                # 	else:
                # 		print("no shift, hor pattern")
                # 		temp_brush = self.brush
                # 		temp_brush.setStyle(Qt.HorPattern)
                # 		painter.setBrush(temp_brush)

                painter.drawRect(QRect(start, end))
                painter1.drawRect(QRect(start, end))

            elif self.shift_pressed == True and self.draw_type != "waiting":
                if abs(starty - endy) >= abs(startx - endx):
                    if self.draw_type == "counter":
                        temp_brush = self.brush
                        temp_brush.setStyle(Qt.VerPattern)
                        painter.setBrush(temp_brush)

                    if startx < endx:
                        painter.drawRect(
                            QRect(QPoint(startx, starty),
                                  QPoint(startx + w, endy)))
                        painter1.drawRect(
                            QRect(QPoint(startx, starty),
                                  QPoint(startx + w, endy)))
                    else:
                        painter.drawRect(
                            QRect(QPoint(startx, starty),
                                  QPoint(startx - w - 2, endy)))
                        painter1.drawRect(
                            QRect(QPoint(startx, starty),
                                  QPoint(startx - w - 2, endy)))
                else:
                    if self.draw_type == "counter":
                        temp_brush = self.brush
                        temp_brush.setStyle(Qt.HorPattern)
                        painter.setBrush(temp_brush)

                    if starty < endy:
                        painter.drawRect(
                            QRect(QPoint(startx, starty),
                                  QPoint(endx, starty + w)))
                        painter1.drawRect(
                            QRect(QPoint(startx, starty),
                                  QPoint(endx, starty + w)))
                    else:
                        painter.drawRect(
                            QRect(QPoint(startx, starty),
                                  QPoint(endx, starty - w - 2)))
                        painter1.drawRect(
                            QRect(QPoint(startx, starty),
                                  QPoint(endx, starty - w - 2)))
            else:
                painter.drawRect(QRect(self.startPoint, self.lastPoint))
                painter1.drawRect(QRect(self.startPoint, self.lastPoint))

    def get_degree(self, start, end):
        startx = start.x()
        starty = start.y()
        endx = end.x()
        endy = end.y()

        if endx >= startx:
            if endx == startx:
                if endy > starty:
                    degree = 90
                else:
                    degree = 270
            else:
                degree = math.atan(
                    (endy - starty + 0.0) / (endx - startx + 0.0))
                degree = (degree / 3.14) * 180
        else:
            degree = math.atan((endy - starty + 0.0) / (startx - endx + 0.0))
            degree = (degree / 3.14) * 180
            degree = 180 - degree

        length = math.sqrt((startx - endx) * (startx - endx) +
                           (starty - endy) * (starty - endy))
        return degree, length

    def mouseReleaseEvent(self, event):
        if event.button() == Qt.LeftButton:
            if self.draw_type != "pillar":
                self.drawing = False
                self.backup_image.insert(0, self.image)
                if self.backup_image.__len__() > self.maximum_undo + 2:
                    self.backup_image.pop()

                if self.draw_type == "railing" or self.draw_type == "wall" or self.draw_type == "pillar" or self.draw_type == "counter":
                    self.backup_hidden_obstacle.insert(
                        0, self.hidden_obstacle_layer)
                    if self.backup_hidden_obstacle.__len__(
                    ) > self.maximum_undo + 2:
                        self.backup_hidden_obstacle.pop()
                else:
                    self.backup_hidden_destination.insert(
                        0, self.hidden_destination_layer)
                    if self.backup_hidden_destination.__len__(
                    ) > self.maximum_undo + 2:
                        self.backup_hidden_destination.pop()

    def keyPressEvent(self, event):
        if event.key() == Qt.Key_Z:
            self.undo()
        elif event.modifiers() == Qt.ShiftModifier:
            self.shift_pressed = True
        elif event.key() == Qt.Key_1:
            self.wall_width_input.setText("1")
            self.wall_width = 1
            self.pillar_width_input.setText("1")
            self.pillar_width = 1
        elif event.key() == Qt.Key_2:
            self.wall_width_input.setText("2")
            self.wall_width = 2
            self.pillar_width_input.setText("2")
            self.pillar_width = 2
        elif event.key() == Qt.Key_3:
            self.wall_width_input.setText("3")
            self.wall_width = 3
            self.pillar_width_input.setText("3")
            self.pillar_width = 3
        elif event.key() == Qt.Key_4:
            self.wall_width_input.setText("4")
            self.wall_width = 4
            self.pillar_width_input.setText("4")
            self.pillar_width = 4
        elif event.key() == Qt.Key_5:
            self.wall_width_input.setText("5")
            self.wall_width = 5
            self.pillar_width_input.setText("5")
            self.pillar_width = 5
        elif event.key() == Qt.Key_6:
            self.wall_width_input.setText("6")
            self.wall_width = 6
            self.pillar_width_input.setText("6")
            self.pillar_width = 6
        elif event.key() == Qt.Key_7:
            self.wall_width_input.setText("7")
            self.wall_width = 7
            self.pillar_width_input.setText("7")
            self.pillar_width = 7
        elif event.key() == Qt.Key_8:
            self.wall_width_input.setText("8")
            self.wall_width = 8
            self.pillar_width_input.setText("8")
            self.pillar_width = 8
        elif event.key() == Qt.Key_9:
            self.wall_width_input.setText("9")
            self.wall_width = 9
            self.pillar_width_input.setText("9")
            self.pillar_width = 9
        elif event.key() == Qt.Key_0:
            self.wall_width_input.setText("10")
            self.wall_width = 10
            self.pillar_width_input.setText("10")
            self.pillar_width = 10
        self.drawTypeChange()

    def undo(self):
        if self.backup_image.__len__() > 1:
            #print(self.backup_image.__len__())
            self.image = self.backup_image[1]
            self.backup_image.pop(0)
            self.update()
        if self.draw_record[0] == "railing" or self.draw_record[
                0] == "wall" or self.draw_record[
                    0] == "pillar" or self.draw_record[0] == "counter":
            if self.backup_hidden_obstacle.__len__() > 1:
                print(self.backup_hidden_obstacle.__len__())
                self.hidden_obstacle_layer = self.backup_hidden_obstacle[1]
                self.backup_hidden_obstacle.pop(0)
                self.update()
        else:
            if self.backup_hidden_destination.__len__() > 1:
                print(self.backup_hidden_destination.__len__())
                self.hidden_destination_layer = self.backup_hidden_destination[
                    1]
                self.backup_hidden_destination.pop(0)
                self.update()
        self.draw_record.pop(0)

    def keyReleaseEvent(self, event):
        if event.key() == Qt.Key_Shift:
            self.shift_pressed = False

    def paintEvent(self, event):
        self.image_label.setPixmap(QPixmap.fromImage(self.image))
Esempio n. 53
0
class Settings(object):

    l = logging.getLogger('Settings')


    def __init__(self, fileName = 'shadow.ini'):
        self.fileName = fileName
        self.tzIdx = 0
        self.mainWindowSize = QSize(1200, 700)
        self.mainWindowPos = QPoint(240, 200)

    def load(self):
        self.l.debug('Loading local settings from {}'.format(self.fileName))
        config = configparser.ConfigParser()
        config.read(self.fileName)

        if config.has_section('common'):
            commonSettings = config['common']
            self.tzIdx = int(commonSettings.get('tz', 0))

        # load main window position and size
        if config.has_section('mainWindow'):
            windowSettings = config['mainWindow']

            # read position
            pos = windowSettings.get('pos', '{},{}'.format(self.mainWindowPos.x(), self.mainWindowPos.y())).split(',')
            self.mainWindowPos = QPoint(int(pos[0]), int(pos[1]))

            # read size
            size = windowSettings.get('size', '{},{}'.format(self.mainWindowSize.width(), self.mainWindowSize.height())).split(',')
            self.mainWindowSize = QSize(int(size[0]), int(size[1]))

        

    def dump(self, channel):
        self.l.debug('Saving local settings ...')
        config = configparser.ConfigParser()

        config.add_section('common')
        config.set('common', 'tz', str(self.tzIdx))

        config.add_section('mainWindow')
        config.set('mainWindow', 'pos', '{},{}'.format(self.mainWindowPos.x(), self.mainWindowPos.y()))
        config.set('mainWindow', 'size', '{},{}'.format(self.mainWindowSize.width(), self.mainWindowSize.height()))

        config.write(channel)

    
    def save(self):
        with open(self.fileName, 'w') as configfile:
            self.dump(configfile)

    def setMainWindowPos(self, pos):
        self.mainWindowPos = pos    

    def setMainWindowSize(self, size):
        self.mainWindowSize = size

    def getMainWindowPos(self):
        return self.mainWindowPos

    def getMainWindowSize(self):
        return self.mainWindowSize

    def getTzIndex(self):
        return self.tzIdx

    def setTzIdx(self, idx):
        self.tzIdx = idx
Esempio n. 54
0
class ImgViewer(QWidget, Ui_ImgViewerWindow):
    def __init__(self, parentWindow):
        super(ImgViewer, self).__init__()
        self.ui = Ui_ImgViewerWindow()
        self.ui.setupUi(self)

        self.parentWindow = parentWindow
        self.setWindowTitle('loading file, please wait ....')
        self.ui.left_PushButton.setFlat(True)
        self.ui.right_PushButton.setFlat(True)
        self.ui.left_PushButton.clicked.connect(self.previousImg)
        self.ui.right_PushButton.clicked.connect(self.nextImg)
        self.left_click = False
        self.flipRGB = False

    def setFileList(self, filelist, YUVFormat, W, H, startframe, totalframe):
        # 获取该格式的解码函数
        decoder = YUVdecoder_dict.get(YUVFormat)
        if decoder is None:
            # 未能成功获取则返回无法解码
            return False
        # 成功获取解码器则准备解码
        # 定义空列表
        self.img_list = []
        self.ui.imgViewer.setText('')
        self.filelist = []
        # 遍历文件列表
        for filename in filelist:
            try:
                # 使用获取的解码函数进行解码得到RGB的原始帧列表
                frame_RGB_list = decoder(filename, W, H, startframe,
                                         totalframe)
            except Exception as e:
                continue
            # 定义img列表用来保存每一帧的QPixmap
            img_RGB_list = []
            # 将原始帧转换到QPixmap并保存到img列表
            for img in frame_RGB_list:
                # 提取图像的通道和尺寸,用于将OpenCV下的image转换成Qimage
                height, width, channel = img.shape
                bytesPerline = 3 * width
                qImg = QImage(img.data, width, height, bytesPerline,
                              QImage.Format_RGB888).rgbSwapped()
                img_RGB_list.append(qImg)
            # img_RGB_list以及文件名存入列表
            self.img_list.append(img_RGB_list)
            self.filelist.append(os.path.split(filename)[1])
        #设置显示第一个YUV文件的第一帧图像
        self.currentImg_RGB_list = self.img_list[0]
        self.currentImg = self.currentImg_RGB_list[0]
        self.setWindowTitle(self.filelist[0] + '-' + str(0))
        self.scaled_img = self.currentImg.scaled(self.size())
        if self.flipRGB:
            self.scaled_img = self.scaled_img.rgbSwapped()
        self.point = QPoint(0, 0)
        return True

    def reciveimgdata(self, img_RGB_list, filename):
        if not img_RGB_list == []:
            # img_RGB_list以及文件名存入列表
            self.img_list.append(img_RGB_list)
            self.filelist.append(os.path.split(filename)[1])
            if len(self.img_list) == 1:
                # 设置显示第一个YUV文件的第一帧图像
                self.ui.imgViewer.setText('')
                self.currentImg_RGB_list = self.img_list[0]
                self.currentImg = self.currentImg_RGB_list[0]
                self.setWindowTitle(self.filelist[0] + '-' + str(0))
                self.scaled_img = self.currentImg.scaled(self.size())
                if self.flipRGB:
                    self.scaled_img = self.scaled_img.rgbSwapped()
                self.point = QPoint(0, 0)
                self.repaint()

        self.decode_thread_finsh.append(self.decode_thread.pop(0))
        if len(self.decode_thread) > 0:
            self.decode_thread[0].start()
        else:
            if len(self.img_list) == 0:
                QMessageBox.critical(self.parentWindow, 'Error',
                                     'unknow error!!', QMessageBox.Ok)
                self.close()

    def setFileList_multithreading(self, filelist, YUVFormat, W, H, startframe,
                                   totalframe):
        # 获取该格式的解码函数
        decoder = YUVdecoder_dict.get(YUVFormat)
        if decoder is None:
            # 未能成功获取则返回无法解码
            return False
        # 定义空列表
        self.img_list = []
        self.filelist = []
        self.decode_thread = []
        self.decode_thread_finsh = []
        # 遍历文件列表
        for filename in filelist:
            decodeThread = YUVDecodeThread(self, filename, YUVFormat, W, H,
                                           startframe, totalframe)
            decodeThread.finsh_signal.connect(self.reciveimgdata)
            self.decode_thread.append(decodeThread)
        self.decode_thread[0].start()
        return True

    def closeEvent(self, event):
        self.parentWindow.show()
        event.accept()

    def draw_img(self, painter):
        painter.drawPixmap(self.point, QPixmap.fromImage(self.scaled_img))

    def paintEvent(self, e):
        if not len(self.img_list) == 0:
            painter = QPainter()
            painter.begin(self)
            self.draw_img(painter)
            painter.end()

    def mouseMoveEvent(self, e):
        if not len(self.img_list) == 0:
            if self.left_click:
                self._endPos = e.pos() - self._startPos
                self.point = self.point + self._endPos
                self._startPos = e.pos()
                self.repaint()

    def mousePressEvent(self, e):
        if not len(self.img_list) == 0:
            if e.button() == Qt.LeftButton:
                self.left_click = True
                self._startPos = e.pos()

    def mouseReleaseEvent(self, e):
        if not len(self.img_list) == 0:
            if e.button() == Qt.LeftButton:
                self.left_click = False
            elif e.button() == Qt.RightButton:
                self.point = QPoint(0, 0)
                self.scaled_img = self.currentImg.scaled(self.size())
                if self.flipRGB:
                    self.scaled_img = self.scaled_img.rgbSwapped()
                self.repaint()
            elif e.button() == Qt.MiddleButton:
                self.scaled_img = self.currentImg.scaled(
                    self.currentImg.width(), self.scaled_img.height())
                if self.flipRGB:
                    self.scaled_img = self.scaled_img.rgbSwapped()
                self.point = QPoint(0, 0)
                self.repaint()

    def mouseDoubleClickEvent(self, event):
        if not len(self.img_list) == 0:
            if event.buttons() == Qt.LeftButton:
                list_index = self.img_list.index(self.currentImg_RGB_list)
                img_RGB_list = self.img_list[list_index]
                img_index = img_RGB_list.index(self.currentImg)
                savefile_name = QFileDialog.getSaveFileName(
                    self, '保存文件',
                    self.filelist[list_index].replace('.yuv', '-') +
                    str(img_index) + '.png', 'Image files(*.png)')
                if savefile_name[0]:
                    self.currentImg.save(savefile_name[0])
            elif event.buttons() == Qt.RightButton:
                self.flipRGB = False if self.flipRGB else True
                self.point = QPoint(0, 0)
                self.scaled_img = self.currentImg.scaled(self.size())
                if self.flipRGB:
                    self.scaled_img = self.scaled_img.rgbSwapped()
                self.repaint()

    def wheelEvent(self, e):
        if not len(self.img_list) == 0:
            if e.angleDelta().y() > 0:
                # 放大图片
                if not self.scaled_img.width(
                ) == 0 and not self.scaled_img.height() == 0:
                    setpsize_x = self.scaled_img.width() / 16
                    setpsize_y = self.scaled_img.height() / 16  #缩放可能导致比例不精确

                    self.scaled_img = self.currentImg.scaled(
                        self.scaled_img.width() + setpsize_x,
                        self.scaled_img.height() + setpsize_y)
                    if self.flipRGB:
                        self.scaled_img = self.scaled_img.rgbSwapped()
                    new_w = e.x() - (self.scaled_img.width() *
                                     (e.x() - self.point.x())) / (
                                         self.scaled_img.width() - setpsize_x)
                    new_h = e.y() - (self.scaled_img.height() *
                                     (e.y() - self.point.y())) / (
                                         self.scaled_img.height() - setpsize_y)
                    self.point = QPoint(new_w, new_h)
                    self.repaint()

            elif e.angleDelta().y() < 0:
                # 缩小图片
                if self.scaled_img.width() > 25 and self.scaled_img.width(
                ) > 25:
                    setpsize_x = self.scaled_img.width() / 16
                    setpsize_y = self.scaled_img.height() / 16  #缩放可能导致比例不精确

                    self.scaled_img = self.currentImg.scaled(
                        self.scaled_img.width() - setpsize_x,
                        self.scaled_img.height() - setpsize_y)
                    if self.flipRGB:
                        self.scaled_img = self.scaled_img.rgbSwapped()
                    new_w = e.x() - (self.scaled_img.width() *
                                     (e.x() - self.point.x())) / (
                                         self.scaled_img.width() + setpsize_x)
                    new_h = e.y() - (self.scaled_img.height() *
                                     (e.y() - self.point.y())) / (
                                         self.scaled_img.height() + setpsize_y)
                    self.point = QPoint(new_w, new_h)
                    self.repaint()

    def resizeEvent(self, e):
        if not len(self.img_list) == 0:
            if self.parent is not None:
                self.scaled_img = self.currentImg.scaled(self.size())
                if self.flipRGB:
                    self.scaled_img = self.scaled_img.rgbSwapped()
                self.point = QPoint(0, 0)
                self.update()

    def previousImg(self):
        if not len(self.img_list) == 0:
            #得到当前显示的文件序号
            list_index = self.img_list.index(self.currentImg_RGB_list)
            img_RGB_list = self.img_list[list_index]
            #得到当前显示的图像是文件的帧序号
            img_index = img_RGB_list.index(self.currentImg)

            #判断当前是否是第一帧
            if img_index == 0:
                #如果当前是第一帧,则判断当前是否是第一个文件
                if list_index == 0:
                    #如果是第一个文件则文件序号更新代到最后一个序号
                    list_index = len(self.img_list) - 1
                else:
                    #否则文件序号更新到前一个文件序号
                    list_index -= 1
                #更新帧序号为文件的最后一帧序号
                img_index = len(self.img_list[list_index]) - 1
            else:
                #否则更新帧序号为前一帧序号,此时文件序号不用更新
                img_index -= 1

            #序号更新完成,代入序号配置当前显示的页面
            self.setWindowTitle(self.filelist[list_index] + '-' +
                                str(img_index))
            self.currentImg_RGB_list = self.img_list[list_index]
            self.currentImg = self.currentImg_RGB_list[img_index]
            self.point = QPoint(0, 0)
            self.scaled_img = self.currentImg.scaled(self.size())
            if self.flipRGB:
                self.scaled_img = self.scaled_img.rgbSwapped()
            self.repaint()

    def nextImg(self):
        if not len(self.img_list) == 0:
            # 得到当前显示的文件序号
            list_index = self.img_list.index(self.currentImg_RGB_list)
            img_RGB_list = self.img_list[list_index]
            # 得到当前显示的图像是文件的帧序号
            img_index = img_RGB_list.index(self.currentImg)

            # 判断当前是否是最后一帧
            if img_index == len(img_RGB_list) - 1:
                # 如果当前是最后一帧,则判断当前是否是最后一个文件
                if list_index == len(self.img_list) - 1:
                    # 如果是最后一个文件则文件序号更新代到第一个序号
                    list_index = 0
                else:
                    # 否则文件序号更新到后一个文件序号
                    list_index += 1
                # 更新帧序号为文件的第一帧序号
                img_index = 0
            else:
                # 否则更新帧序号为后一帧序号,此时文件序号不用更新
                img_index += 1

            # 序号更新完成,代入序号配置当前显示的页面
            self.setWindowTitle(self.filelist[list_index] + '-' +
                                str(img_index))
            self.currentImg_RGB_list = self.img_list[list_index]
            self.currentImg = self.currentImg_RGB_list[img_index]
            self.point = QPoint(0, 0)
            self.scaled_img = self.currentImg.scaled(self.size())
            if self.flipRGB:
                self.scaled_img = self.scaled_img.rgbSwapped()
            self.repaint()
Esempio n. 55
0
File: gui.py Progetto: fqez/sandbox
	def paintEvent(self, event):
		  
		painter = QPainter(self)
		painter.setPen(self.pen)
		painter.setBrush(self.brush)
		if self.antialiased:
			painter.setRenderHint(QPainter.Antialiasing)

		angle_step = 360 / self.n_states

		painter.save()	#Save_1. Save the state of the system (push matrix)
		painter.translate(self.dist_center.x(), self.dist_center.y())		# go to the center of the render area
		painter.rotate(-180)	#to start painting from the left side of the circle (clockwise)

		#center of the circumference where through we are going to paint our states 
		x = self.dist_radius * math.cos(0)	
		y = self.dist_radius * math.sin(0)


		for h in range(self.n_states):

			rot = angle_step * h 	# each state is equidistant from the others. We paint them in circles

			painter.save()			#Save_2
			painter.rotate(rot)		#now our system is pointing to the next state to be drawn
			painter.translate(x,y)	#now our origin is in the center of the next state to be drawn

			#if the state is active, fill it green
			if self.machine.getState(h).isActive():	
				painter.setBrush(self.greenGradientBrush)			
			painter.drawEllipse(QPoint(0,0), self.state_radius, self.state_radius)	#draw the new state

			#global position of transformed coordinates (before any transformation, origin at top-left corner)
			gx = painter.worldTransform().map(QPoint(0,0)).x()
			gy = painter.worldTransform().map(QPoint(0,0)).y()
			self.machine.getState(h).setPos(gx, gy)		#store the center of the state without any transformation applied

			# text transformation. Our origin is still in the center of the current state
			painter.save()			#Save_3
			painter.rotate(180)		#making the text go vertical
			painter.rotate(-rot)	#undoing the rotation made for painting the state. No the text is horizontal
			font = painter.font();
			font.setPixelSize(self.state_radius*.4);
			painter.setFont(font);
			rect = QRect(-self.state_radius, -self.state_radius, self.state_radius*2, self.state_radius*2)
			painter.drawText(rect, Qt.AlignCenter, self.machine.getState(h).getName());
			painter.restore()	#Restore_3
			#end text transformation

			painter.restore()	#Restore_2
			
		painter.restore()	#Restore_1. Restore the state of the system (pop matrix)

		
		#drawing transitions. Line between states
		painter.save()	# Save_4
		pptv = QTransform()		#Define a new transformation. Needed to rotate the system along other axis than Z
		pptv.translate(0, self.height())	#We are now at the bottom-left corner of the screen
		pptv.rotate(-180, Qt.XAxis)			#Rotate along the X-axis so now we are in a typical cartesian system.
		painter.setTransform(pptv)			#Apply the transformation
		states = self.machine.getStates()
		for state in states:
			transitions = state.getTransitions()
			for transition in transitions:
				#get the center of the origin and destination states in our current system state
				orig = QPoint(state.getPos()[0], state.getPos()[1])
				end = QPoint(self.machine.getState(transition.getStateEnd()).getPos()[0], self.machine.getState(transition.getStateEnd()).getPos()[1])
				# get those coordinates without transformation
				orig2 = QPoint(painter.worldTransform().map(orig))
				end2 = QPoint(painter.worldTransform().map(end))

				#get the angle between states centers and the horizon
				angle = math.atan2(end2.y() - orig2.y(), end2.x() - orig2.x())

				#get the coordinates of the starting point of the transition (it starts in the bound of the state, not in the center)
				newX = self.state_radius * math.cos(angle) + orig2.x()
				newY = self.state_radius * math.sin(angle) + orig2.y()
				#now the transition starts at the border, not in the center
				orig2.setX(newX)
				orig2.setY(newY)

				#same for the destination state
				angle2 = math.atan2(orig2.y() - end2.y(), orig2.x() - end2.x())
				newX2 = self.state_radius * math.cos(angle2) + end2.x()
				newY2 = self.state_radius * math.sin(angle2) + end2.y()
				end2.setX(newX2)
				end2.setY(newY2)

				#draw the line between the origin and destination states
				painter.drawLine(orig2, end2)
				#get the start and the end of the transition untransformed
				init = QPoint(painter.worldTransform().map(orig2))
				end = QPoint(painter.worldTransform().map(end2))
				#store that info
				transition.setOrig(init.x(), init.y())
				transition.setDest(end.x(), end.y())	
				transition.setAngle(angle)
		painter.restore() #Restore_4


		#Appliying style to the transitions
		painter.setPen(QPen(QColor(Qt.gray), 3))
		for state in self.machine.getStates():
			for transition in state.getTransitions():
				#get the start and end coordinates of the transition
				i = QPoint(transition.getOrig()[0], transition.getOrig()[1])
				o = QPoint(transition.getDest()[0], transition.getDest()[1])			
				painter.drawPolyline(i, o)

				#Drawing the arrow at the end of the transition
				painter.save()	#Save_5
				painter.setPen(QPen(QColor(Qt.gray), 2))
				painter.translate(transition.getDest()[0],transition.getDest()[1])	#Go to the end of the transition
				painter.rotate(90 - transition.getAngle()*180/math.pi)		#Rotate to point in the direction of the transition

				#coordinates of the arrow (triangle)
				a = QPoint(0,0)
				b = QPoint(-5,10)
				c = QPoint(5,10)

				#coordinates of the arrow untransformed
				a1 = painter.worldTransform().map(a)
				b1 = painter.worldTransform().map(b)
				c1 = painter.worldTransform().map(c)

				#Drawin the actual arrow
				pointer = QPolygon([a,b,c])
				painter.drawPolygon(pointer)
				painter.restore()	#Restore_5

				#For the animation of the transition
				painter.save()	#Save_6
				if transition.isActive():	#if the current transition is the active one the wave function will be running, so it's updating the canvas

					painter.setPen(QPen(QColor(Qt.green), 3))
					painter.drawPolyline(i,o)
					
					painter.setPen(QPen(QColor(Qt.gray), 3))
					painter.drawPolyline(self.poly(self.pts))

					#Draw the arrow in the active state (red arrow)
					painter.setBrush(QBrush(QColor(255, 0, 0)))
					painter.setPen(QPen(QColor(Qt.red), 2))
					pointer = QPolygon([a1,b1,c1])
					painter.drawPolygon(pointer)
					
					#Ball that follows the line animation
					for x, y in self.pts:
						painter.drawEllipse(QRectF(self.pts[0][0] - 4, self.pts[0][1] - 4, 8, 8))
				painter.restore()	#Restore_6

				#Painting the text of the transition
				painter.save()	#Save_7
				pptv = QTransform()
				painter.setPen(QPen(QColor(Qt.black), 3))
				#get the middle point of the transition
				middleX = (transition.getOrig()[0] + transition.getDest()[0]) /2	
				middleY = (transition.getOrig()[1] + transition.getDest()[1]) /2
				pptv.translate(middleX, middleY)	#translate to that point
				painter.setTransform(pptv)			#apply the transformation
				font = painter.font();
				font.setPixelSize(self.state_radius*.2);
				painter.setFont(font);
				rect = QRect(-self.state_radius, -self.state_radius, self.state_radius*2, self.state_radius*2)
				name = str(transition.getId())+ '. ' + transition.getName()
				painter.drawText(rect, Qt.AlignCenter, name)
				painter.restore()	#Restore_7


  
		#paint the actual canvas
		painter.setPen(self.palette().dark().color())
		painter.setBrush(Qt.NoBrush)
		painter.drawRect(QRect(0, 0, self.width() - 1, self.height() - 1))
Esempio n. 56
0
    def screenToTileCoords(self, x, y):
        p = RenderParams(self.map())
        if (p.staggerX):
            if p.staggerEven:
                x -= p.tileWidth
            else:
                x -= p.sideOffsetX
        else:
            if p.staggerEven:
                y -= p.tileHeight
            else:
                y -= p.sideOffsetY
        # Start with the coordinates of a grid-aligned tile
        lenx = p.tileWidth + p.sideLengthX
        leny = p.tileHeight + p.sideLengthY
        referencePoint = QPoint(math.floor(x / lenx), math.floor(y / leny))
        # Relative x and y position on the base square of the grid-aligned tile
        rel = QVector2D(x - referencePoint.x() * lenx,
                        y - referencePoint.y() * leny)
        # Adjust the reference point to the correct tile coordinates
        if p.staggerX:
            staggerAxisIndex = referencePoint.x()
        else:
            staggerAxisIndex = referencePoint.y()

        staggerAxisIndex *= 2

        if (p.staggerEven):
            staggerAxisIndex += 1

        if p.staggerX:
            referencePoint.setX(staggerAxisIndex)
        else:
            referencePoint.setY(staggerAxisIndex)

        # Determine the nearest hexagon tile by the distance to the center
        centers = [0, 0, 0, 0]
        if (p.staggerX):
            left = int(p.sideLengthX / 2)
            centerX = left + p.columnWidth
            centerY = int(p.tileHeight / 2)
            centers[0] = QVector2D(left, centerY)
            centers[1] = QVector2D(centerX, centerY - p.rowHeight)
            centers[2] = QVector2D(centerX, centerY + p.rowHeight)
            centers[3] = QVector2D(centerX + p.columnWidth, centerY)
        else:
            top = int(p.sideLengthY / 2)
            centerX = int(p.tileWidth / 2)
            centerY = top + p.rowHeight
            centers[0] = QVector2D(centerX, top)
            centers[1] = QVector2D(centerX - p.columnWidth, centerY)
            centers[2] = QVector2D(centerX + p.columnWidth, centerY)
            centers[3] = QVector2D(centerX, centerY + p.rowHeight)

        nearest = 0
        minDist = 1.7976931348623157e+308
        for i in range(4):
            center = centers[i]
            dc = (center - rel).lengthSquared()
            if (dc < minDist):
                minDist = dc
                nearest = i

        offsetsStaggerX = [
            QPoint(0, 0),
            QPoint(+1, -1),
            QPoint(+1, 0),
            QPoint(+2, 0),
        ]
        offsetsStaggerY = [
            QPoint(0, 0),
            QPoint(-1, +1),
            QPoint(0, +1),
            QPoint(0, +2),
        ]
        if p.staggerX:
            offsets = offsetsStaggerX
        else:
            offsets = offsetsStaggerY
        return QPointF(referencePoint + offsets[nearest])
Esempio n. 57
0
    def _incline_line(self, path: QtGui.QPainterPath, point1: QtCore.QPoint,
                      point2: QtCore.QPoint, span_left: list,
                      span_right: list):
        #绘制站间的斜线
        #TODO 暂未考虑直接跨过无定义区域的情况
        width = self.graphWidget.scene.width() - \
                self.graphWidget.margins["left"] - self.graphWidget.margins["right"]
        if point1.inRange and point2.inRange:
            if point1.x() <= point2.x():
                path.lineTo(point2)
            else:
                # 跨界运行线
                dx = point2.x() - point1.x() + width
                dy = point2.y() - point1.y()
                ax = width + self.graphWidget.margins["left"] - point1.x()
                h = ax * dy / dx
                span_right.append(point1.y() + h)
                span_left.append(point1.y() + h)
                path.lineTo(self.graphWidget.margins["left"] + width,
                            point1.y() + h)
                path.moveTo(self.graphWidget.margins["left"], point1.y() + h)
                path.lineTo(point2)
        elif not point1.inRange and not point2.inRange:
            return

        elif point1.inRange:
            #右侧点越界
            dx = point2.x() - point1.x() + width
            dy = point2.y() - point1.y()
            ax = width + self.graphWidget.margins["left"] - point1.x()
            h = ax * dy / dx
            span_right.append(point1.y() + h)
            path.lineTo(self.graphWidget.margins["left"] + width,
                        point1.y() + h)

        else:
            #左侧点越界
            dx = point2.x() - point1.x() + width
            dy = point2.y() - point1.y()
            ax = width + self.graphWidget.margins["left"] - point1.x()
            h = ax * dy / dx
            span_left.append(point1.y() + h)
            path.moveTo(self.graphWidget.margins["left"], point1.y() + h)
            path.lineTo(point2)
class Example(QWidget):
    overlay: QImage  #Overlay(Накладываем) Picture on Window
    timer: QTimer  #Timet init
    painter: QPainter

    Colors: list
    arr_points: list
    DeltaX: int
    DeltaY: int
    SelfHeight: int
    LastAngle: int
    Size: list
    LastMousePosition: QPoint

    def __init__(self):
        super().__init__()
        self.initUI()

    def keyPressEvent(self, event):
        if event.key() == 16777216:
            self.FileSaving(FILE_NAME)
            sys.exit()  #Programm Closing

    def GetStationPopularity(self, station_name, trends_object):
        kw_list = station_name
        trends_object.build_payload(kw_list,
                                    cat=0,
                                    timeframe='today 5-y',
                                    geo='',
                                    gprop='')

        interest = trends_object.interest_over_time()
        return interest.mean()
        #plt.plot(interest[station_name])
        #plt.show()

    def mousePressEvent(self, event):
        mousePoint = event.pos()
        self.LastMousePosition = mousePoint

        if event.button() == 2:
            WindowW = self.frameGeometry().width()  #   WindowSize
            WindowH = self.frameGeometry().height()  #  WindowSize
            imgH = self.overlay.height()  # Original Picture Size
            imgW = self.overlay.width()  #  Original Picture Size

            img = self.overlay.scaledToHeight(self.SelfHeight,
                                              Qt.FastTransformation)

            #AdjX = (WindowW-img.width())/2
            ResultX = imgW * (mousePoint.x() - self.DeltaX) / img.width()

            ResultY = imgH / 100 * ((mousePoint.y() - self.DeltaY) /
                                    (self.SelfHeight / 100))
            #eraser = 7

            self.painter.drawEllipse(QPoint(ResultX, ResultY), RADIUS, RADIUS)

            #self.painter.eraseRect(QRect(QPoint(ResultX-RADIUS/2-eraser, ResultY-RADIUS/2-eraser), QPoint(ResultX+radius/2+eraser, ResultY+radius/2+eraser)))
            self.arr_points.append((ResultX, ResultY))
            #print([(round(x[0]), round(x[1])) for x in self.arr_points])
            self.update()  #Redraw

    def FileSaving(self, fileName: str):
        with open(fileName, 'w') as f:
            for item in self.arr_points:
                f.write(';'.join(str(x) for x in item) + '\n')
            f.close()

    def NameReading(self, fileName: str):
        with open(fileName, 'r') as f:
            names = f.read().split('\n')
        f.close()
        #print(names)
        return names

    def FileDrawing(self, fileName: str):
        penLine = QPen(QColor(Qt.red))
        penLine.setWidth(10)
        #my_file = Path('!StationsLine12.txt')
        #print(my_file.isfile())

        for n in range(1):
            penEllipse = QPen(self.Colors[int(n / 2)])
            penEllipse.setWidth(5)

            data = []
            path = fileName + str(n / 2 + 1) + '.txt'
            my_file = Path(path)
            #print(os.listdir())

            if my_file.is_file():
                with open(fileName + str(n / 2 + 1) + '.txt', 'r') as f:
                    data = f.read().split('\n')
                    f.close()

                lastX = None
                lastY = None
                Point1 = None
                Point2 = None
                Startlen = None
                x = 0
                y = 0
                i = 0

                #print(self.NameReading('!Stations.txt'))

                for line in data:
                    x, y = line.split(';')

                    #if lastX is not None or lastY is not None:
                    self.painter.setPen(penLine)
                    #Point1 = QPoint(lastX, lastY)
                    #Point2 = QPoint(float(x), float(y))
                    #self.painter.drawLine(Point1, Point2)

                    self.painter.setPen(penEllipse)
                    penLine = QPen(QColor(Qt.red))
                    self.painter.setBrush(QColor(Qt.white))

                    self.painter.drawEllipse(
                        float(x) - RADIUS / 100 * self.Size[i],
                        float(y) - RADIUS / 100 * self.Size[i],
                        (RADIUS / 100 * self.Size[i]) * 2,
                        (RADIUS / 100 * self.Size[i]) * 2)
                    i += 1

    def mouseReleaseEvent(self, event):
        self.point = None

    def closeEvent(self, event):
        #self.FileSaving(FILE_NAME)
        sys.exit()  #Programm Closing

    def initUI(self):
        self.Colors = [
            QColor(228, 37, 24),  #1
            QColor(75, 175, 79),  #2
            QColor(5, 114, 185),  #3
            QColor(36, 188, 239),  #4
            QColor(146, 82, 51),  #5
            QColor(239, 128, 39),  #6
            QColor(148, 63, 144),  #7
            QColor(255, 209, 30),  #8
            QColor(173, 172, 172),  #9
            QColor(185, 206, 31),  #10
            QColor(134, 204, 206),  #11
            QColor(186, 200, 232),  #12
            QColor(68, 143, 201),  #13
            QColor(232, 68, 57),  #14
        ]

        self.pytrends = TrendReq(hl='en-US', tz=360)

        stationsName = self.NameReading('!Stations.txt')
        #print(stationsName[0:5])
        self.Size = self.GetStationPopularity(stationsName[0:5], self.pytrends)
        #print(self.Size)
        print(list(self.Size))
        self.showMaximized()
        #self.showNormal()
        self.arr_points = []
        self.LastAngle = 0
        self.timer = QTimer()  #Timer init
        self.timer.timeout.connect(self.update)  # Timer init
        self.setWindowTitle('Moscow Metro Map Poppularity')  # Title
        self.point = None
        self.DeltaX = 0
        self.DeltaY = 0
        self.SelfHeight = self.frameGeometry().height()
        self.LastMousePosition = QPoint(0, 0)

        self.overlay = QImage()
        self.overlay.load('Moscow Metro Map Stations Popularity\\MainMap.bmp')

        pen = QPen(QColor(Qt.red))
        pen.setWidth(5)
        self.painter = QPainter(self.overlay)
        self.painter.setPen(pen)
        self.painter.Antialiasing = True

        self.timer.start(1000 / 50)  #50 кадров в секунду

        self.FileDrawing(FILE_NAME)

    def paintEvent(self, event):
        painter = QPainter()
        painter.begin(self)
        #windowsWidth = self.frameGeometry().width()
        windowsHeight = self.frameGeometry().height()

        img = self.overlay.scaledToHeight(self.SelfHeight, 0)
        painter.drawImage(self.DeltaX, self.DeltaY, img)
        painter.end()
        del painter

    def mouseMoveEvent(self, event):
        CurentPos = event.pos()
        self.DeltaX -= self.LastMousePosition.x() - CurentPos.x()
        self.DeltaY -= self.LastMousePosition.y() - CurentPos.y()
        #self.LastMousePosition = mousePoint
        self.LastMousePosition = event.pos()

    def wheelEvent(self, event):
        #print(str(event.angleDelta()))

        self.SelfHeight += (event.angleDelta().y()) / 10
        self.LastAngle = event.angleDelta().y()

    def resizeEvent(self, event):
        self.SelfHeight = self.frameGeometry().height()
Esempio n. 59
0
class GLWidget(QOpenGLWidget):
    def __init__(self, parent=None):
        super(GLWidget, self).__init__(parent)

        midnight = QTime(0, 0, 0)
        random.seed(midnight.secsTo(QTime.currentTime()))

        self.object = 0
        self.xRot = 0
        self.yRot = 0
        self.zRot = 0
        self.image = QImage()
        self.bubbles = []
        self.lastPos = QPoint()

        self.trolltechGreen = QColor.fromCmykF(0.40, 0.0, 1.0, 0.0)
        self.trolltechPurple = QColor.fromCmykF(0.39, 0.39, 0.0, 0.0)

        self.animationTimer = QTimer()
        self.animationTimer.setSingleShot(False)
        self.animationTimer.timeout.connect(self.animate)
        self.animationTimer.start(25)

        self.setAutoFillBackground(False)
        self.setMinimumSize(200, 200)
        self.setWindowTitle("Overpainting a Scene")

    def setXRotation(self, angle):
        angle = self.normalizeAngle(angle)
        if angle != self.xRot:
            self.xRot = angle

    def setYRotation(self, angle):
        angle = self.normalizeAngle(angle)
        if angle != self.yRot:
            self.yRot = angle

    def setZRotation(self, angle):
        angle = self.normalizeAngle(angle)
        if angle != self.zRot:
            self.zRot = angle

    def initializeGL(self):
        self.gl = self.context().versionFunctions()
        self.gl.initializeOpenGLFunctions()

        self.object = self.makeObject()

    def mousePressEvent(self, event):
        self.lastPos = event.pos()

    def mouseMoveEvent(self, event):
        dx = event.x() - self.lastPos.x()
        dy = event.y() - self.lastPos.y()

        if event.buttons() & Qt.LeftButton:
            self.setXRotation(self.xRot + 8 * dy)
            self.setYRotation(self.yRot + 8 * dx)
        elif event.buttons() & Qt.RightButton:
            self.setXRotation(self.xRot + 8 * dy)
            self.setZRotation(self.zRot + 8 * dx)

        self.lastPos = event.pos()

    def paintEvent(self, event):
        self.makeCurrent()

        self.gl.glMatrixMode(self.gl.GL_MODELVIEW)
        self.gl.glPushMatrix()

        self.setClearColor(self.trolltechPurple.darker())
        self.gl.glShadeModel(self.gl.GL_SMOOTH)
        self.gl.glEnable(self.gl.GL_DEPTH_TEST)
        #self.gl.glEnable(self.gl.GL_CULL_FACE)
        self.gl.glEnable(self.gl.GL_LIGHTING)
        self.gl.glEnable(self.gl.GL_LIGHT0)
        self.gl.glEnable(self.gl.GL_MULTISAMPLE)
        self.gl.glLightfv(self.gl.GL_LIGHT0, self.gl.GL_POSITION,
                (0.5, 5.0, 7.0, 1.0))

        self.setupViewport(self.width(), self.height())

        self.gl.glClear(
                self.gl.GL_COLOR_BUFFER_BIT | self.gl.GL_DEPTH_BUFFER_BIT)
        self.gl.glLoadIdentity()
        self.gl.glTranslated(0.0, 0.0, -10.0)
        self.gl.glRotated(self.xRot / 16.0, 1.0, 0.0, 0.0)
        self.gl.glRotated(self.yRot / 16.0, 0.0, 1.0, 0.0)
        self.gl.glRotated(self.zRot / 16.0, 0.0, 0.0, 1.0)
        self.gl.glCallList(self.object)

        self.gl.glMatrixMode(self.gl.GL_MODELVIEW)
        self.gl.glPopMatrix()

        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing)

        for bubble in self.bubbles:
            if bubble.rect().intersects(QRectF(event.rect())):
                bubble.drawBubble(painter)

        self.drawInstructions(painter)
        painter.end()

    def resizeGL(self, width, height):
        self.setupViewport(width, height)

    def showEvent(self, event):
        self.createBubbles(20 - len(self.bubbles))

    def sizeHint(self):
        return QSize(400, 400)

    def makeObject(self):
        list = self.gl.glGenLists(1)
        self.gl.glNewList(list, self.gl.GL_COMPILE)

        self.gl.glEnable(self.gl.GL_NORMALIZE)
        self.gl.glBegin(self.gl.GL_QUADS)

        self.gl.glMaterialfv(self.gl.GL_FRONT, self.gl.GL_DIFFUSE,
                (self.trolltechGreen.red()/255.0,
                 self.trolltechGreen.green()/255.0,
                 self.trolltechGreen.blue()/255.0, 1.0))

        x1 = +0.06
        y1 = -0.14
        x2 = +0.14
        y2 = -0.06
        x3 = +0.08
        y3 = +0.00
        x4 = +0.30
        y4 = +0.22

        self.quad(x1, y1, x2, y2, y2, x2, y1, x1)
        self.quad(x3, y3, x4, y4, y4, x4, y3, x3)

        self.extrude(x1, y1, x2, y2)
        self.extrude(x2, y2, y2, x2)
        self.extrude(y2, x2, y1, x1)
        self.extrude(y1, x1, x1, y1)
        self.extrude(x3, y3, x4, y4)
        self.extrude(x4, y4, y4, x4)
        self.extrude(y4, x4, y3, x3)

        NumSectors = 200

        for i in range(NumSectors):
            angle1 = (i * 2 * math.pi) / NumSectors
            x5 = 0.30 * math.sin(angle1)
            y5 = 0.30 * math.cos(angle1)
            x6 = 0.20 * math.sin(angle1)
            y6 = 0.20 * math.cos(angle1)

            angle2 = ((i + 1) * 2 * math.pi) / NumSectors
            x7 = 0.20 * math.sin(angle2)
            y7 = 0.20 * math.cos(angle2)
            x8 = 0.30 * math.sin(angle2)
            y8 = 0.30 * math.cos(angle2)

            self.quad(x5, y5, x6, y6, x7, y7, x8, y8)

            self.extrude(x6, y6, x7, y7)
            self.extrude(x8, y8, x5, y5)

        self.gl.glEnd()

        self.gl.glEndList()
        return list

    def quad(self, x1, y1, x2, y2, x3, y3, x4, y4):
        self.gl.glNormal3d(0.0, 0.0, -1.0)
        self.gl.glVertex3d(x1, y1, -0.05)
        self.gl.glVertex3d(x2, y2, -0.05)
        self.gl.glVertex3d(x3, y3, -0.05)
        self.gl.glVertex3d(x4, y4, -0.05)

        self.gl.glNormal3d(0.0, 0.0, 1.0)
        self.gl.glVertex3d(x4, y4, +0.05)
        self.gl.glVertex3d(x3, y3, +0.05)
        self.gl.glVertex3d(x2, y2, +0.05)
        self.gl.glVertex3d(x1, y1, +0.05)

    def extrude(self, x1, y1, x2, y2):
        self.setColor(self.trolltechGreen.darker(250 + int(100 * x1)))

        self.gl.glNormal3d((x1 + x2)/2.0, (y1 + y2)/2.0, 0.0)
        self.gl.glVertex3d(x1, y1, +0.05)
        self.gl.glVertex3d(x2, y2, +0.05)
        self.gl.glVertex3d(x2, y2, -0.05)
        self.gl.glVertex3d(x1, y1, -0.05)

    def normalizeAngle(self, angle):
        while angle < 0:
            angle += 360 * 16
        while angle > 360 * 16:
            angle -= 360 * 16
        return angle

    def createBubbles(self, number):
        for i in range(number):
            position = QPointF(self.width()*(0.1 + 0.8*random.random()),
                               self.height()*(0.1 + 0.8*random.random()))
            radius = min(self.width(), self.height())*(0.0125 + 0.0875*random.random())
            velocity = QPointF(self.width()*0.0125*(-0.5 + random.random()),
                               self.height()*0.0125*(-0.5 + random.random()))

            self.bubbles.append(Bubble(position, radius, velocity))

    def animate(self):
        for bubble in self.bubbles:
            bubble.move(self.rect())

        self.update()

    def setupViewport(self, width, height):
        side = min(width, height)
        self.gl.glViewport((width - side) // 2, (height - side) // 2, side,
                side)

        self.gl.glMatrixMode(self.gl.GL_PROJECTION)
        self.gl.glLoadIdentity()
        self.gl.glOrtho(-0.5, +0.5, +0.5, -0.5, 4.0, 15.0)
        self.gl.glMatrixMode(self.gl.GL_MODELVIEW)

    def drawInstructions(self, painter):
        text = "Click and drag with the left mouse button to rotate the Qt " \
                "logo."
        metrics = QFontMetrics(self.font())
        border = max(4, metrics.leading())

        rect = metrics.boundingRect(0, 0, self.width() - 2*border,
                int(self.height()*0.125), Qt.AlignCenter | Qt.TextWordWrap,
                text)
        painter.setRenderHint(QPainter.TextAntialiasing)
        painter.fillRect(QRect(0, 0, self.width(), rect.height() + 2*border),
                QColor(0, 0, 0, 127))
        painter.setPen(Qt.white)
        painter.fillRect(QRect(0, 0, self.width(), rect.height() + 2*border),
                QColor(0, 0, 0, 127))
        painter.drawText((self.width() - rect.width())/2, border, rect.width(),
                rect.height(), Qt.AlignCenter | Qt.TextWordWrap, text)

    def setClearColor(self, c):
        self.gl.glClearColor(c.redF(), c.greenF(), c.blueF(), c.alphaF())

    def setColor(self, c):
        self.gl.glColor4f(c.redF(), c.greenF(), c.blueF(), c.alphaF())
Esempio n. 60
0
class GLWidget(QOpenGLWidget):
    xRotationChanged = pyqtSignal(int)
    yRotationChanged = pyqtSignal(int)
    zRotationChanged = pyqtSignal(int)

    def __init__(self, parent=None):
        super(GLWidget, self).__init__(parent)

        self.setFocusPolicy(Qt.StrongFocus)

        self.object = 0
        self.xRot = 0
        self.yRot = 0
        self.zRot = 0
        self.translateX = 0.0
        self.translateY = 0.0
        self.zoom = -15.0
        self.ctlPressed = False

        self.matrix = Matrix(5, 5, 5)

        self.lastPos = QPoint()

        self.selectedX = 0
        self.selectedY = 0
        self.selectedZ = 4

        self.trolltechGreen = QColor.fromCmykF(0.40, 0.0, 1.0, 0.0)
        self.trolltechPurple = QColor.fromCmykF(0.39, 0.39, 0.0, 0.0)
        self.Black = QColor.fromCmykF(0.0, 0.0, 0.0, 0.0, 0.0)

        self.selectedColor = self.trolltechGreen

    def getOpenglInfo(self):
        info = """
            Vendor: {0}
            Renderer: {1}
            OpenGL Version: {2}
            Shader Version: {3}
        """.format(gl.glGetString(gl.GL_VENDOR),
                   gl.glGetString(gl.GL_RENDERER),
                   gl.glGetString(gl.GL_VERSION),
                   gl.glGetString(gl.GL_SHADING_LANGUAGE_VERSION))

        return info

    def minimumSizeHint(self):
        return QSize(50, 50)

    def sizeHint(self):
        return QSize(800, 600)

    def setXRotation(self, angle):
        angle = self.normalizeAngle(angle)
        if angle != self.xRot:
            self.xRot = angle
            self.xRotationChanged.emit(angle)
            self.update()

    def setYRotation(self, angle):
        angle = self.normalizeAngle(angle)
        if angle != self.yRot:
            self.yRot = angle
            self.yRotationChanged.emit(angle)
            self.update()

    def setZRotation(self, angle):
        angle = self.normalizeAngle(angle)
        if angle != self.zRot:
            self.zRot = angle
            self.zRotationChanged.emit(angle)
            self.update()

    def initializeGL(self):
        print(self.getOpenglInfo())

        self.setClearColor(self.trolltechPurple.darker())
        self.object = self.makeObject()
        gl.glShadeModel(gl.GL_FLAT)
        gl.glEnable(gl.GL_DEPTH_TEST)
        gl.glEnable(gl.GL_CULL_FACE)
        gl.glCullFace(gl.GL_FRONT)

    def paintGL(self):
        gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)
        gl.glLoadIdentity()
        gl.glTranslatef(self.translateX, self.translateY, self.zoom)
        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.glCallList(self.object)

    def resizeGL(self, width, height):
        side = min(width, height)
        if side < 0:
            return

        gl.glMatrixMode(gl.GL_PROJECTION)
        gl.glLoadIdentity()
        glu.gluPerspective(45, width / height, 1, 100.0)
        gl.glMatrixMode(gl.GL_MODELVIEW)

    def mousePressEvent(self, event):
        self.lastPos = event.pos()

        if event.buttons() & Qt.MiddleButton:
            self.resetView()
            self.updateGL()

    def mouseMoveEvent(self, event):
        dx = event.x() - self.lastPos.x()
        dy = event.y() - self.lastPos.y()

        if not self.ctlPressed:
            if event.buttons() & Qt.LeftButton:
                self.setXRotation(self.xRot + 8 * dy)
                self.setYRotation(self.yRot + 8 * dx)
            elif event.buttons() & Qt.RightButton:
                self.setXRotation(self.xRot + 8 * dy)
                self.setZRotation(self.zRot + 8 * dx)

            self.lastPos = event.pos()
        else:
            if event.buttons() & Qt.LeftButton:
                self.translateX += dx / 100
                self.translateY += -dy / 100

                self.update()
                self.lastPos = event.pos()

    def wheelEvent(self, event):

        numdegrees = event.angleDelta() / 8
        numdegrees = numdegrees / 15

        if -200 <= self.zoom + numdegrees.y() <= 0:
            self.zoom += numdegrees.y()

        self.update()

    def keyPressEvent(self, event):
        if event.key() == Qt.Key_Shift:
            self.ctlPressed = True
        elif event.key() == Qt.Key_Left and self.selectedX > 0:
            self.matrix.blocks[self.selectedX, self.selectedY,
                               self.selectedZ].select()
            self.selectedX -= 1
            self.matrix.blocks[self.selectedX, self.selectedY,
                               self.selectedZ].select()
            self.updateGL()
        elif event.key(
        ) == Qt.Key_Right and self.selectedX < self.matrix.width - 1:
            self.matrix.blocks[self.selectedX, self.selectedY,
                               self.selectedZ].select()
            self.selectedX += 1
            self.matrix.blocks[self.selectedX, self.selectedY,
                               self.selectedZ].select()
            self.updateGL()
        elif event.key() == Qt.Key_Minus and self.selectedY > 0:
            self.matrix.blocks[self.selectedX, self.selectedY,
                               self.selectedZ].select()
            self.selectedY -= 1
            self.matrix.blocks[self.selectedX, self.selectedY,
                               self.selectedZ].select()
            self.updateGL()
        elif event.key(
        ) == Qt.Key_Plus and self.selectedY < self.matrix.height - 1:
            self.matrix.blocks[self.selectedX, self.selectedY,
                               self.selectedZ].select()
            self.selectedY += 1
            self.matrix.blocks[self.selectedX, self.selectedY,
                               self.selectedZ].select()
            self.updateGL()
        elif event.key() == Qt.Key_Up and self.selectedZ > 0:
            self.matrix.blocks[self.selectedX, self.selectedY,
                               self.selectedZ].select()
            self.selectedZ -= 1
            self.matrix.blocks[self.selectedX, self.selectedY,
                               self.selectedZ].select()
            self.updateGL()
        elif event.key(
        ) == Qt.Key_Down and self.selectedZ < self.matrix.depth - 1:
            self.matrix.blocks[self.selectedX, self.selectedY,
                               self.selectedZ].select()
            self.selectedZ += 1
            self.matrix.blocks[self.selectedX, self.selectedY,
                               self.selectedZ].select()
            self.updateGL()
        elif event.key() == Qt.Key_F5:
            self.matrix.blocks[self.selectedX, self.selectedY,
                               self.selectedZ].color = self.selectedColor
            self.matrix.blocks[self.selectedX, self.selectedY,
                               self.selectedZ].activate()
            self.updateGL()

    def keyReleaseEvent(self, event):
        if event.key() == Qt.Key_Shift:
            self.ctlPressed = False

    def makeObject(self):
        genList = gl.glGenLists(1)
        gl.glNewList(genList, gl.GL_COMPILE)

        self.matrix.paint()

        gl.glEndList()

        return genList

    def normalizeAngle(self, angle):
        while angle < 0:
            angle += 360 * 16
        while angle > 360 * 16:
            angle -= 360 * 16

        return angle

    def setClearColor(self, c):
        gl.glClearColor(c.redF(), c.greenF(), c.blueF(), c.alphaF())

    def setColor(self, c):
        gl.glColor4f(c.redF(), c.greenF(), c.blueF(), c.alphaF())

    def setMatrixSize(self, x, y, z):
        self.matrix = Matrix(x, y, z)
        self.updateGL()

    def resetView(self):
        self.xRot = 0
        self.yRot = 0
        self.zRot = 0
        self.translateX = 0.0
        self.translateY = 0.0
        self.zoom = -15.0

        self.updateGL()

    def updateGL(self):
        self.object = self.makeObject()
        self.paintGL()
        self.update()

    def setSelectedColor(self, color):
        self.selectedColor = color