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
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