class SnapshotFreehandGrabber(QWidget):
    """
    Class implementing a grabber widget for a freehand snapshot region.
    
    @signal grabbed(QPixmap) emitted after the region was grabbed
    """
    grabbed = pyqtSignal(QPixmap)
    
    def __init__(self):
        """
        Constructor
        """
        super(SnapshotFreehandGrabber, self).__init__(
            None,
            Qt.X11BypassWindowManagerHint | Qt.WindowStaysOnTopHint |
            Qt.FramelessWindowHint | Qt.Tool)
        
        self.__selection = QPolygon()
        self.__mouseDown = False
        self.__newSelection = False
        self.__handleSize = 10
        self.__showHelp = True
        self.__grabbing = False
        self.__dragStartPoint = QPoint()
        self.__selectionBeforeDrag = QPolygon()
        self.__locale = QLocale()
        
        self.__helpTextRect = QRect()
        self.__helpText = self.tr(
            "Select a region using the mouse. To take the snapshot,"
            " press the Enter key or double click. Press Esc to quit.")
        
        self.__pixmap = QPixmap()
        self.__pBefore = QPoint()
        
        self.setMouseTracking(True)
        
        QTimer.singleShot(200, self.__initialize)
    
    def __initialize(self):
        """
        Private slot to initialize the rest of the widget.
        """
        self.__desktop = QApplication.desktop()
        x = self.__desktop.x()
        y = self.__desktop.y()
        if qVersion() >= "5.0.0":
            self.__pixmap = QApplication.screens()[0].grabWindow(
                self.__desktop.winId(), x, y,
                self.__desktop.width(), self.__desktop.height())
        else:
            self.__pixmap = QPixmap.grabWindow(
                self.__desktop.winId(), x, y,
                self.__desktop.width(), self.__desktop.height())
        self.resize(self.__pixmap.size())
        self.move(x, y)
        self.setCursor(Qt.CrossCursor)
        self.show()

        self.grabMouse()
        self.grabKeyboard()
        self.activateWindow()
    
    def paintEvent(self, evt):
        """
        Protected method handling paint events.
        
        @param evt paint event (QPaintEvent)
        """
        if self.__grabbing:     # grabWindow() should just get the background
            return
        
        painter = QPainter(self)
        pal = QPalette(QToolTip.palette())
        font = QToolTip.font()
        
        handleColor = pal.color(QPalette.Active, QPalette.Highlight)
        handleColor.setAlpha(160)
        overlayColor = QColor(0, 0, 0, 160)
        textColor = pal.color(QPalette.Active, QPalette.Text)
        textBackgroundColor = pal.color(QPalette.Active, QPalette.Base)
        painter.drawPixmap(0, 0, self.__pixmap)
        painter.setFont(font)
        
        pol = QPolygon(self.__selection)
        if not self.__selection.boundingRect().isNull():
            # Draw outline around selection.
            # Important: the 1px-wide outline is *also* part of the
            # captured free-region
            pen = QPen(handleColor, 1, Qt.SolidLine, Qt.SquareCap,
                       Qt.BevelJoin)
            painter.setPen(pen)
            painter.drawPolygon(pol)
            
            # Draw the grey area around the selection.
            grey = QRegion(self.rect())
            grey = grey - QRegion(pol)
            painter.setClipRegion(grey)
            painter.setPen(Qt.NoPen)
            painter.setBrush(overlayColor)
            painter.drawRect(self.rect())
            painter.setClipRect(self.rect())
            drawPolygon(painter, pol, handleColor)
        
        if self.__showHelp:
            painter.setPen(textColor)
            painter.setBrush(textBackgroundColor)
            self.__helpTextRect = painter.boundingRect(
                self.rect().adjusted(2, 2, -2, -2),
                Qt.TextWordWrap, self.__helpText).translated(
                -self.__desktop.x(), -self.__desktop.y())
            self.__helpTextRect.adjust(-2, -2, 4, 2)
            drawPolygon(painter, self.__helpTextRect, textColor,
                        textBackgroundColor)
            painter.drawText(
                self.__helpTextRect.adjusted(3, 3, -3, -3),
                Qt.TextWordWrap, self.__helpText)
        
        if self.__selection.isEmpty():
            return
        
        # The grabbed region is everything which is covered by the drawn
        # rectangles (border included). This means that there is no 0px
        # selection, since a 0px wide rectangle will always be drawn as a line.
        boundingRect = self.__selection.boundingRect()
        txt = "{0}, {1} ({2} x {3})".format(
            self.__locale.toString(boundingRect.x()),
            self.__locale.toString(boundingRect.y()),
            self.__locale.toString(boundingRect.width()),
            self.__locale.toString(boundingRect.height())
        )
        textRect = painter.boundingRect(self.rect(), Qt.AlignLeft, txt)
        boundingRect = textRect.adjusted(-4, 0, 0, 0)
        
        polBoundingRect = pol.boundingRect()
        if (textRect.width() <
            polBoundingRect.width() - 2 * self.__handleSize) and \
           (textRect.height() <
            polBoundingRect.height() - 2 * self.__handleSize) and \
           polBoundingRect.width() > 100 and \
           polBoundingRect.height() > 100:
            # center, unsuitable for small selections
            boundingRect.moveCenter(polBoundingRect.center())
            textRect.moveCenter(polBoundingRect.center())
        elif polBoundingRect.y() - 3 > textRect.height() and \
                polBoundingRect.x() + textRect.width() < self.rect().width():
            # on top, left aligned
            boundingRect.moveBottomLeft(
                QPoint(polBoundingRect.x(), polBoundingRect.y() - 3))
            textRect.moveBottomLeft(
                QPoint(polBoundingRect.x() + 2, polBoundingRect.y() - 3))
        elif polBoundingRect.x() - 3 > textRect.width():
            # left, top aligned
            boundingRect.moveTopRight(
                QPoint(polBoundingRect.x() - 3, polBoundingRect.y()))
            textRect.moveTopRight(
                QPoint(polBoundingRect.x() - 5, polBoundingRect.y()))
        elif (polBoundingRect.bottom() + 3 + textRect.height() <
              self.rect().bottom()) and \
                polBoundingRect.right() > textRect.width():
            # at bottom, right aligned
            boundingRect.moveTopRight(
                QPoint(polBoundingRect.right(), polBoundingRect.bottom() + 3))
            textRect.moveTopRight(
                QPoint(polBoundingRect.right() - 2,
                       polBoundingRect.bottom() + 3))
        elif polBoundingRect.right() + textRect.width() + 3 < \
                self.rect().width():
            # right, bottom aligned
            boundingRect.moveBottomLeft(
                QPoint(polBoundingRect.right() + 3, polBoundingRect.bottom()))
            textRect.moveBottomLeft(
                QPoint(polBoundingRect.right() + 5, polBoundingRect.bottom()))
        
        # If the above didn't catch it, you are running on a very
        # tiny screen...
        drawPolygon(painter, boundingRect, textColor, textBackgroundColor)
        painter.drawText(textRect, Qt.AlignHCenter, txt)
        
        if (polBoundingRect.height() > self.__handleSize * 2 and
            polBoundingRect.width() > self.__handleSize * 2) or \
           not self.__mouseDown:
            painter.setBrush(Qt.transparent)
            painter.setClipRegion(QRegion(pol))
            painter.drawPolygon(QPolygon(self.rect()))
    
    def mousePressEvent(self, evt):
        """
        Protected method to handle mouse button presses.
        
        @param evt mouse press event (QMouseEvent)
        """
        self.__pBefore = evt.pos()
        
        self.__showHelp = not self.__helpTextRect.contains(evt.pos())
        if evt.button() == Qt.LeftButton:
            self.__mouseDown = True
            self.__dragStartPoint = evt.pos()
            self.__selectionBeforeDrag = QPolygon(self.__selection)
            if not self.__selection.containsPoint(evt.pos(), Qt.WindingFill):
                self.__newSelection = True
                self.__selection = QPolygon()
            else:
                self.setCursor(Qt.ClosedHandCursor)
        elif evt.button() == Qt.RightButton:
            self.__newSelection = False
            self.__selection = QPolygon()
            self.setCursor(Qt.CrossCursor)
        self.update()
    
    def mouseMoveEvent(self, evt):
        """
        Protected method to handle mouse movements.
        
        @param evt mouse move event (QMouseEvent)
        """
        shouldShowHelp = not self.__helpTextRect.contains(evt.pos())
        if shouldShowHelp != self.__showHelp:
            self.__showHelp = shouldShowHelp
            self.update()
        
        if self.__mouseDown:
            if self.__newSelection:
                p = evt.pos()
                self.__selection.append(p)
            else:
                # moving the whole selection
                p = evt.pos() - self.__pBefore  # Offset
                self.__pBefore = evt.pos()  # save position for next iteration
                self.__selection.translate(p)
            
            self.update()
        else:
            if self.__selection.boundingRect().isEmpty():
                return
            
            if self.__selection.containsPoint(evt.pos(), Qt.WindingFill):
                self.setCursor(Qt.OpenHandCursor)
            else:
                self.setCursor(Qt.CrossCursor)
    
    def mouseReleaseEvent(self, evt):
        """
        Protected method to handle mouse button releases.
        
        @param evt mouse release event (QMouseEvent)
        """
        self.__mouseDown = False
        self.__newSelection = False
        if self.__selection.containsPoint(evt.pos(), Qt.WindingFill):
            self.setCursor(Qt.OpenHandCursor)
        self.update()
    
    def mouseDoubleClickEvent(self, evt):
        """
        Protected method to handle mouse double clicks.
        
        @param evt mouse double click event (QMouseEvent)
        """
        self.__grabRegion()
    
    def keyPressEvent(self, evt):
        """
        Protected method to handle key presses.
        
        @param evt key press event (QKeyEvent)
        """
        if evt.key() == Qt.Key_Escape:
            self.grabbed.emit(QPixmap())
        elif evt.key() in [Qt.Key_Enter, Qt.Key_Return]:
            self.__grabRegion()
        else:
            evt.ignore()
    
    def __grabRegion(self):
        """
        Private method to grab the selected region (i.e. do the snapshot).
        """
        pol = QPolygon(self.__selection)
        if not pol.isEmpty():
            self.__grabbing = True
            
            xOffset = self.__pixmap.rect().x() - pol.boundingRect().x()
            yOffset = self.__pixmap.rect().y() - pol.boundingRect().y()
            translatedPol = pol.translated(xOffset, yOffset)
            
            pixmap2 = QPixmap(pol.boundingRect().size())
            pixmap2.fill(Qt.transparent)
            
            pt = QPainter()
            pt.begin(pixmap2)
            if pt.paintEngine().hasFeature(QPaintEngine.PorterDuff):
                pt.setRenderHints(
                    QPainter.Antialiasing |
                    QPainter.HighQualityAntialiasing |
                    QPainter.SmoothPixmapTransform,
                    True)
                pt.setBrush(Qt.black)
                pt.setPen(QPen(QBrush(Qt.black), 0.5))
                pt.drawPolygon(translatedPol)
                pt.setCompositionMode(QPainter.CompositionMode_SourceIn)
            else:
                pt.setClipRegion(QRegion(translatedPol))
                pt.setCompositionMode(QPainter.CompositionMode_Source)
            
            pt.drawPixmap(pixmap2.rect(), self.__pixmap, pol.boundingRect())
            pt.end()
            
            self.grabbed.emit(pixmap2)
    def contextMenuEvent(self, event):
        module_area = 0
        for i in self.rect_list:
            if i.rect_begin.x() < event.pos().x() < i.rect_end.x(
            ) and i.rect_begin.y() < event.pos().y() < i.rect_end.y():
                module_area = 1
                contextMenu = QMenu(self)

                # Add Input Port action is used to add input port to both code and block
                portAction = contextMenu.addAction("Add Port")
                renameAction = contextMenu.addAction("Rename Module")
                removeModuleAction = contextMenu.addAction("Remove Module")

                action = contextMenu.exec_(self.mapToGlobal(event.pos()))

                if action == portAction:
                    self.myshow = AddPort(i)
                    self.myshow.setWindowTitle("Add Port")
                    self.myshow.show()
                    self.update()
                elif action == renameAction:
                    self.myshow = RenameModule(i, self.forbidden_module_names)
                    self.myshow.setWindowTitle("Rename Module")
                    self.myshow.show()
                    self.update()
                elif action == removeModuleAction:
                    self.forbidden_module_names.remove(i.center_text)
                    self.rect_list.remove(i)
                    self.update()

        port_area = "no_port"
        if module_area == 0:
            for r in self.rect_list:
                temp_port = 0
                for i in r.in_port_list:
                    polygon = QPolygon(i.points)
                    if polygon.containsPoint(event.pos(), Qt.OddEvenFill):
                        port_area = "input"
                        temp_port = i
                for i in r.inout_port_list:
                    polygon = QPolygon(i.points)
                    if polygon.containsPoint(event.pos(), Qt.OddEvenFill):
                        port_area = "inout"
                        temp_port = i
                for i in r.out_port_list:
                    polygon = QPolygon(i.points)
                    if polygon.containsPoint(event.pos(), Qt.OddEvenFill):
                        port_area = "output"
                        temp_port = i

                if port_area != "no_port":
                    contextMenu = QMenu(self)
                    removeAction = contextMenu.addAction("Remove")
                    renameAction = contextMenu.addAction("Rename Port")

                    action = contextMenu.exec_(self.mapToGlobal(event.pos()))

                    if action == removeAction:
                        if port_area == "input":
                            r.in_port_list.remove(temp_port)
                            r.update()
                            self.update()
                        elif port_area == "inout":
                            r.inout_port_list.remove(temp_port)
                            r.update()
                            self.update()
                        elif port_area == "output":
                            r.out_port_list.remove(temp_port)
                            r.update()
                            self.update()
                        r.update()
                    elif action == renameAction:
                        self.myshow = RenamePort(temp_port, r)
                        self.myshow.setWindowTitle("Rename Port")
                        self.myshow.show()
                    break

        if port_area == "no_port" and module_area == 0:
            contextMenu = QMenu(self)

            # Add Input Port action is used to add input port to both code and block
            addModuleAction = contextMenu.addAction("Add Module")

            action = contextMenu.exec_(self.mapToGlobal(event.pos()))
            if action == addModuleAction:
                intersect = 0
                rect_begin_dragged = event.pos()
                for j in self.rect_list:
                    rect_begin_x = j.rect_begin.x() - 2 * j.Tri_In_H
                    rect_begin_y = j.rect_begin.y() - 10
                    rect_width = j.width + 3 * j.Tri_In_H
                    rect_height = j.height + 20
                    rect_temp = QRect(rect_begin_x, rect_begin_y, rect_width,
                                      rect_height)
                    rect_dragged = QRect(
                        rect_begin_dragged.x() - 2 * j.Tri_In_H,
                        rect_begin_dragged.y() - 10, 200 + 3 * j.Tri_In_H,
                        200 + 20)
                    if rect_temp.intersects(rect_dragged):
                        intersect = 1
                        break

                if intersect == 0:
                    tempModule = Module()
                    i = 0
                    while 1:
                        if 'case_block_' + str(
                                i) not in self.forbidden_module_names:
                            tempModule.center_text = 'case_block_' + str(i)
                            tempModule.rect_begin = event.pos()
                            tempModule.rect_end = event.pos() + QtCore.QPoint(
                                200, 200)
                            tempModule.update()
                            self.rect_list.append(tempModule)
                            self.forbidden_module_names.append(
                                tempModule.center_text)
                            # To call paintEvent method, update method is run.
                            # When module is created, to show it on canvas paintEvent must be called
                            self.update()
                            break
                        i = i + 1
                else:
                    self.myshow = ErrorMessage(
                        'Module cannot be created because it is too close to other modules'
                    )
def voronoi_function(list_players, list_opponents, field):
    points = []
    for o in list_opponents:
        points.append(o.getLocation())
    for p in list_players:
        points.append(p.getLocation())

    if len(list_players + list_opponents) == 0:
        return

    if len(list_players + list_opponents) == 1:
        field = [
            QPoint(field[0][0], field[0][1]),
            QPoint(field[1][0], field[1][1]),
            QPoint(field[2][0], field[2][1]),
            QPoint(field[3][0], field[3][1])
        ]
        if list_players:
            list_players[0].polygon.setPolygon(QPolygonF(QPolygon(field)))
            return
        if list_opponents:
            list_opponents[0].polygon.setPolygon(QPolygonF(QPolygon(field)))
            return

    if len(points) == 2:
        startpoints = np.array(points)
        mitte = startpoints.mean(axis=0)
        #mitte = [(points[0][0]+points[1][0])/2, (points[0][1]+points[1][1])/2]
        v = startpoints[0] - startpoints[1]
        if (v[1] == 0):
            n = np.array([0, 1])
        else:
            n = np.array([1, -v[0] / v[1]])
        p1 = mitte + 5000 * n
        p2 = mitte + (-5000) * n
        pc = pyclipper.Pyclipper()
        pc.AddPath(field, pyclipper.PT_CLIP, True)
        pc.AddPath([p1, p2], pyclipper.PT_SUBJECT, False)
        line = pc.Execute2(pyclipper.CT_INTERSECTION, pyclipper.PFT_NONZERO,
                           pyclipper.PFT_NONZERO)
        line = pyclipper.PolyTreeToPaths(line)
        firstPoly, secondPoly = splitPolygon(line[0], field)
        firstpol = QPolygon()
        secondpol = QPolygon()

        for p in firstPoly:
            firstpol.append(QPoint(p[0], p[1]))
        for p in secondPoly:
            secondpol.append(QPoint(p[0], p[1]))

        for p in list_opponents + list_players:
            if firstpol.containsPoint(
                    QPoint(p.getLocation()[0],
                           p.getLocation()[1]), Qt.OddEvenFill):
                p.polygon.setPolygon(QPolygonF(firstpol))
            if secondpol.containsPoint(
                    QPoint(p.getLocation()[0],
                           p.getLocation()[1]), Qt.OddEvenFill):
                p.polygon.setPolygon(QPolygonF(secondpol))
        return

    pointArray = np.asarray(points)
    vor = Voronoi(pointArray)
    vertices = vor.ridge_vertices
    eckpunkte = vor.vertices
    #print("Points: " + str(vor.points))
    #print("Ridge_Vertices: " + str(vertices))
    #print("Vertices: " + str(eckpunkte.tolist()))
    #print("Ridge_Points: " + str(vor.ridge_points))
    #print("Regions: " + str(vor.regions))
    #print("Point_regions" + str(vor.point_region))

    pointidx = 0
    val = []
    for point in vor.points:  ##iteration über punkte
        lines = []
        poly = []
        schnittpunkte = []
        far_line = []
        regions = vor.regions
        regionidx = vor.point_region.tolist()[pointidx]
        if min(regions[regionidx],
               default=-1) >= 0:  ##behandlung falls polygon geschlossen
            for vidx in regions[regionidx]:
                poly.append([vor.vertices[vidx][0], vor.vertices[vidx][1]])

            pc = pyclipper.Pyclipper()
            pc.AddPath(field, pyclipper.PT_CLIP, True)
            pc.AddPath(poly, pyclipper.PT_SUBJECT, True)
            poly = pc.Execute2(pyclipper.CT_INTERSECTION,
                               pyclipper.PFT_NONZERO, pyclipper.PFT_NONZERO)
            poly = pyclipper.PolyTreeToPaths(
                poly)  #Hinzufügen der Eckpunkte der closed Polygone
            poly = poly[0]

        else:
            ridgeidx = 0
            field_copy = deepcopy(field)

            for punkte_paar in vor.ridge_points:  ##iteration über die kanten die aus dem punkt gebildet werden
                punkte_paar = np.asarray(punkte_paar)

                if np.any(punkte_paar == pointidx):
                    if min(vor.ridge_vertices[ridgeidx]
                           ) >= 0:  ##definierte linien des offenen polygons
                        li = [
                            vor.vertices[vor.ridge_vertices[ridgeidx]
                                         [0]].tolist(),
                            vor.vertices[vor.ridge_vertices[ridgeidx]
                                         [1]].tolist()
                        ]
                        lines.append([li[0], li[1]])
                        val.append(li)

                    else:  ##für offenes polygon
                        center = pointArray.mean(axis=0)
                        v = vor.vertices[vor.ridge_vertices[ridgeidx]][
                            1]  # finite end Voronoi vertex
                        ausgangspunkt1 = pointArray[punkte_paar[1]]
                        ausgangspunkt2 = pointArray[punkte_paar[0]]
                        t = ausgangspunkt1 - ausgangspunkt2  # tangent
                        x = np.linalg.norm(t)
                        t = t / x
                        n = np.array([-t[1], t[0]])  # normal
                        midpoint = pointArray[punkte_paar].mean(axis=0)
                        far_point = v + np.sign(np.dot(midpoint - center,
                                                       n)) * n * 50000
                        p1 = [v[0], v[1]]
                        p2 = [far_point[0], far_point[1]]
                        far_line.append(p2)
                        line = [p1, p2]
                        lines.append(line)
                ridgeidx += 1

        if lines:
            poly = ltp(lines)
            pc = pyclipper.Pyclipper()
            pc.AddPath(field, pyclipper.PT_CLIP, True)
            pc.AddPath(poly, pyclipper.PT_SUBJECT, True)
            poly = pc.Execute2(pyclipper.CT_INTERSECTION,
                               pyclipper.PFT_NONZERO, pyclipper.PFT_NONZERO)
            poly = pyclipper.PolyTreeToPaths(poly)
            if poly:
                poly = poly[0]

            pc = pyclipper.Pyclipper()
            pc.AddPath(field, pyclipper.PT_CLIP, True)
            pc.AddPath(far_line, pyclipper.PT_SUBJECT, False)
            intersect_far = pc.Execute2(pyclipper.CT_INTERSECTION,
                                        pyclipper.PFT_NONZERO,
                                        pyclipper.PFT_NONZERO)
            intersect_far = pyclipper.PolyTreeToPaths(intersect_far)
            if intersect_far:
                intersect_far = intersect_far[0]
                for p in intersect_far:
                    idx = poly.index(p)
                    idx2 = idx + 1
                    if idx2 > len(poly) - 1:
                        idx2 = -1
                    if poly[idx2] in intersect_far:
                        iscp = poly[idx - 1]
                    elif poly[idx - 1] in intersect_far:
                        iscp = poly[idx2]
                    for eck in field:
                        if checkPointOnLine(p, [iscp, eck]):
                            poly.pop(idx)
                            poly.insert(idx, eck)

        add_player_poly(poly, pointidx, list_players, list_opponents)

        pointidx += 1

    return val
Exemple #4
0
def containspoly(poly1: QPolygon, poly2: QPolygon):
    for point_index in range(poly2.size()-1):
        if not poly1.containsPoint(poly2.point(point_index), Qt.OddEvenFill):
            return False
    return True