| 
					
				 | 
			
			
				@@ -1,203 +1,19 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import numpy as np 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-from PyQt5.QtCore import Qt 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-from PyQt5.QtGui import QImage, QPixmap, QPainter, QColor, QPolygon 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-from PyQt5.QtCore import QPoint, QSize, QRect 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QTextEdit 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-from PyQt5.QtWidgets import QHBoxLayout, QVBoxLayout, QLabel, QFrame 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-class Window(QMainWindow): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+# TODO: anti-aliased version, fill_coords_aa? 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+def fill_coords(img, fn, color): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     """ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    Simple application window to render the environment into 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    Fill pixels of an image with coordinates matching a filter function 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     """ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def __init__(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        super().__init__() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.setWindowTitle('MiniGrid Gym Environment') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        # Image label to display the rendering 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.imgLabel = QLabel() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.imgLabel.setFrameStyle(QFrame.Panel | QFrame.Sunken) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        # Text box for the mission 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.missionBox = QTextEdit() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.missionBox.setReadOnly(True) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.missionBox.setMinimumSize(400, 100) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        # Center the image 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        hbox = QHBoxLayout() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        hbox.addStretch(1) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        hbox.addWidget(self.imgLabel) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        hbox.addStretch(1) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        # Arrange widgets vertically 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        vbox = QVBoxLayout() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        vbox.addLayout(hbox) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        vbox.addWidget(self.missionBox) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        # Create a main widget for the window 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        mainWidget = QWidget(self) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.setCentralWidget(mainWidget) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        mainWidget.setLayout(vbox) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        # Show the application window 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.show() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.setFocus() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.closed = False 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        # Callback for keyboard events 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.keyDownCb = None 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def closeEvent(self, event): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.closed = True 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def setPixmap(self, pixmap): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.imgLabel.setPixmap(pixmap) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def setText(self, text): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.missionBox.setPlainText(text) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def setKeyDownCb(self, callback): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.keyDownCb = callback 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def keyPressEvent(self, e): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if self.keyDownCb == None: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        keyName = None 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if e.key() == Qt.Key_Left: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            keyName = 'LEFT' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        elif e.key() == Qt.Key_Right: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            keyName = 'RIGHT' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        elif e.key() == Qt.Key_Up: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            keyName = 'UP' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        elif e.key() == Qt.Key_Down: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            keyName = 'DOWN' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        elif e.key() == Qt.Key_Space: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            keyName = 'SPACE' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        elif e.key() == Qt.Key_Return: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            keyName = 'RETURN' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        elif e.key() == Qt.Key_Alt: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            keyName = 'ALT' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        elif e.key() == Qt.Key_Control: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            keyName = 'CTRL' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        elif e.key() == Qt.Key_PageUp: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            keyName = 'PAGE_UP' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        elif e.key() == Qt.Key_PageDown: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            keyName = 'PAGE_DOWN' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        elif e.key() == Qt.Key_Backspace: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            keyName = 'BACKSPACE' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        elif e.key() == Qt.Key_Escape: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            keyName = 'ESCAPE' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if keyName == None: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.keyDownCb(keyName) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-class Renderer: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def __init__(self, width, height, ownWindow=False): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.width = width 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.height = height 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.img = QImage(width, height, QImage.Format_RGB888) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.painter = QPainter() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.window = None 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if ownWindow: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            self.app = QApplication([]) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            self.window = Window() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def close(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        """ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Deallocate resources used 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        """ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        pass 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def beginFrame(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.painter.begin(self.img) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.painter.setRenderHint(QPainter.Antialiasing, False) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        # Clear the background 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.painter.setBrush(QColor(0, 0, 0)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.painter.drawRect(0, 0, self.width - 1, self.height - 1) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def endFrame(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.painter.end() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if self.window: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if self.window.closed: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                self.window = None 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            else: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                self.window.setPixmap(self.getPixmap()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                self.app.processEvents() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def getPixmap(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return QPixmap.fromImage(self.img) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def getArray(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        """ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Get a numpy array of RGB pixel values. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        The array will have shape (height, width, 3) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        """ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        numBytes = self.width * self.height * 3 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        buf = self.img.bits().asstring(numBytes) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        output = np.frombuffer(buf, dtype='uint8') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        output = output.reshape((self.height, self.width, 3)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return output 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def push(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.painter.save() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def pop(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.painter.restore() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def rotate(self, degrees): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.painter.rotate(degrees) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def translate(self, x, y): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.painter.translate(x, y) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def scale(self, x, y): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.painter.scale(x, y) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def setLineColor(self, r, g, b, a=255): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.painter.setPen(QColor(r, g, b, a)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def setColor(self, r, g, b, a=255): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.painter.setBrush(QColor(r, g, b, a)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def setLineWidth(self, width): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        pen = self.painter.pen() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        pen.setWidthF(width) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.painter.setPen(pen) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def drawLine(self, x0, y0, x1, y1): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.painter.drawLine(x0, y0, x1, y1) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def drawCircle(self, x, y, r): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        center = QPoint(x, y) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.painter.drawEllipse(center, r, r) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def drawPolygon(self, points): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        """Takes a list of points (tuples) as input""" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        points = map(lambda p: QPoint(p[0], p[1]), points) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.painter.drawPolygon(QPolygon(points)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def drawPolyline(self, points): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        """Takes a list of points (tuples) as input""" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        points = map(lambda p: QPoint(p[0], p[1]), points) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.painter.drawPolyline(QPolygon(points)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def fillRect(self, x, y, width, height, r, g, b, a=255): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.painter.fillRect(QRect(x, y, width, height), QColor(r, g, b, a)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for y in range(img.shape[0]): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        for x in range(img.shape[1]): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            yf = y / img.shape[0] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            xf = x / img.shape[1] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if fn(xf, yf): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                img[y, x] = color 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return img 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 def point_in_circle(cx, cy, r): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     def fn(x, y): 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -235,12 +51,3 @@ def point_in_triangle(a, b, c): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return (u >= 0) and (v >= 0) and (u + v) < 1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     return fn 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-# TODO: anti-aliased version, fill_coords_aa? 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-def fill_coords(img, fn, color): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    for y in range(img.shape[0]): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        for x in range(img.shape[1]): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            yf = y / img.shape[0] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            xf = x / img.shape[1] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if fn(xf, yf): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                img[y, x] = color 
			 |