def addCanvasPolygon(self, ps, color=(0, 0, 0), fill=True, stroke=False, **kwargs): polygon = QtGui.QPolygonF() for ver in ps: polygon.append(QtCore.QPointF(*ver)) color = [int(c * 255) for c in color] pen = QtGui.QPen(QtGui.QColor(*color), 1, PenStile_DashLine) self.painter.setPen(pen) self.painter.setBrush(QtGui.QColor(0, 0, 0)) self.painter.drawPolygon(polygon)
def polyClose(self): #make into hot key not button if self.measuring_area: if self.line_count > 2: #cant make polygon w/ two lines self.measuring_area = False A = self.A.calcArea() self.areaValues = np.append(self.areaValues, A) #add area values #draw permanent polygon points = [ QtCore.QPointF(x,y) for x,y in zip( self.A.x, self.A.y ) ] self.scene.polyItem2 = QGraphicsPolygonItem(QtGui.QPolygonF(points)) self.scene.polyItem2.setBrush( QtGui.QBrush(QtGui.QColor(255,255,255,127)) ) if self.scene.polyItem: self.scene.removeItem(self.scene.polyItem) #remove mouseover polygon self.scene.polyItem = False #remove mouseover polygon self.scene.removeItem(self.scene.testline) self.scene.testline = False self.scene.addItem(self.scene.polyItem2) #shade in polygon self.parent().statusbar.showMessage('Polygon area measurement completed') self.parent().areaButton.setChecked(False) self.parent().bezier.setEnabled(True) #make bezier fit available again else: print("cannot draw polygon with fewer than three vertices")
def mousePressEvent(self, event): #http://pyqt.sourceforge.net/Docs/PyQt4/qgraphicsscenemouseevent.html #https://stackoverflow.com/questions/21197658/how-to-get-pixel-on-qgraphicspixmapitem-on-a-qgraphicsview-from-a-mouse-click data = self.mapToScene(event.pos()) #draw piecewise lines for non-width measurements rules = [self.measuring_length, self.measuring_angle, self.measuring_area] if self.scene.testline and self._thispos and any(rules): start = self._thispos end = QtCore.QPointF(data) if self._lastpos and self.measuring_angle: a = self._lastpos - self._thispos b = data - self._thispos a = np.array([a.x(), a.y()]) b = np.array([b.x(), b.y()]) self.measuring_angle = False t = np.arccos(np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))) t *= 180 / np.pi #convert to degrees self.T.update(t) self.angleValues = np.append(self.angleValues,t) self.parent().statusbar.showMessage('Angle measurement complete') self.parent().angleButton.setChecked(False) self.parent().bezier.setEnabled(True) self.scene.realline = QGraphicsLineItem(QtCore.QLineF(start, end)) self.scene.addItem(self.scene.realline) #Collect piecewise line start/end points self._lastpos = self._thispos # save old position value self._thispos = QtCore.QPointF(data) # update current position if self.measuring_length: self.L.update(data.x(), data.y()) # update total length self.line_count += 1 elif self.measuring_area: self.line_count += 1 intersect = False if self.line_count > 2: #cant make polygon w/ two lines intersect, xi, yi, k = self.A.checkIntersect(data.x(),data.y()) self.parent().areaButton.setEnabled(True) if intersect: self.measuring_area = False self.A.update(xi,yi) #update with intersect point self.A.x, self.A.y = self.A.x[k:], self.A.y[k:] #only use points after intersection A = self.A.calcArea() self.areaValues = np.append(self.areaValues, A) #add area values #draw permanent polygon points = [ QtCore.QPointF(x,y) for x,y in zip( self.A.x, self.A.y ) ] self.scene.polyItem2 = QGraphicsPolygonItem(QtGui.QPolygonF(points)) self.scene.polyItem2.setBrush( QtGui.QBrush(QtGui.QColor(255,255,255,127)) ) self.scene.removeItem(self.scene.polyItem) #remove mouseover polygon self.scene.polyItem = False #remove mouseover polygon self.scene.addItem(self.scene.polyItem2) #shade in polygon self.parent().statusbar.showMessage('Polygon area measurement completed') self.parent().areaButton.setChecked(False) self.parent().bezier.setEnabled(True) #make bezier fit available again QApplication.setOverrideCursor(QtCore.Qt.ArrowCursor) #change cursor else: self.A.update(data.x(),data.y()) #update with click point #https://stackoverflow.com/questions/30898846/qgraphicsview-items-not-being-placed-where-they-should-be if self.measuring_widths: #measure widths, snap to spines k = int(self.k / 2) + 1 #same origin for spine on either side x0, y0 = self.xp[k], self.yp[k] x1, y1 = data.x(), data.y() #perpindicular slopes vx = self.slopes[:,k][1] vy = -self.slopes[:,k][0] A = np.matrix([[vx, -vy], [vy, vx]]) b = np.array([x1 - x0, y1 - y0]) t = np.linalg.solve(A,b) xi = x0 + t[0]*vx yi = y0 + t[0]*vy self.W.update(xi,yi) p = QtCore.QPointF(xi, yi) s = 10 #dot size self.scene.ellipseItem = QGraphicsEllipseItem(0, 0, s, s) self.scene.ellipseItem.setPos(p.x() - s / 2, p.y() - s / 2) qb = QtGui.QBrush() qb.setColor(QtGui.QColor('red')) self.scene.ellipseItem.setBrush(qb) self.scene.ellipseItem.setFlag( QGraphicsItem.GraphicsItemFlag.ItemIgnoresTransformations, False) #size stays small, but doesnt translate if false self.scene.addItem(self.scene.ellipseItem) self.k += 1 if self.k < self.nspines: self.d[str(self.k)].setPen(QtGui.QPen( QtGui.QColor('yellow'))) #Highlight next spine if self.k == self.nspines: self.parent().statusbar.showMessage('Width measurements complete') self.measuring_widths = False self.parent().widthsButton.setEnabled(False) self.parent().widthsButton.setChecked(False) self.parent().bezier.setEnabled(True) width = np.sqrt( (self.W.x[1::2] - self.W.x[0::2])**2 + (self.W.y[1::2] - self.W.y[0::2])**2) #calculate widths self.widths[-1] = width
def mouseMoveEvent(self, event): data = self.mapToScene(event.position().toPoint()) rules = [self.measuring_length, self.measuring_angle, self.measuring_area] modifiers = QApplication.keyboardModifiers() if modifiers == QtCore.Qt.KeyboardModifier.ShiftModifier and self.oldPos: QApplication.setOverrideCursor(QtCore.Qt.CursorShape.OpenHandCursor) self.newPos = data delta = self.newPos - self.oldPos self.translate(delta.x(), delta.y()) elif (any(rules) or self.measuring_widths): QApplication.setOverrideCursor(QtCore.Qt.CursorShape.CrossCursor) #change cursor else: QApplication.setOverrideCursor(QtCore.Qt.CursorShape.ArrowCursor) #change cursor #dragging line if self._thispos and any(rules): if self.measuring_length: self.parent().statusbar.showMessage( 'Click to place next point... double click to finish') if self.measuring_area: self.parent().statusbar.showMessage( 'Click to place next point... close polygon to finish') if self.measuring_angle: self.parent().statusbar.showMessage( 'Click point to define vector') end = QtCore.QPointF(data)#self.mapToScene(event.pos())) start = self._thispos if self.measuring_angle and self._lastpos: start = self._thispos if self.scene.testline: #remove old line self.scene.removeItem(self.scene.testline) self.scene.testline = False if self.measuring_area and self.line_count > 2: intersect, xi, yi, k = self.A.checkIntersect(data.x(),data.y()) if self.scene.area_ellipseItem: #remove existing intersect self.scene.removeItem(self.scene.area_ellipseItem) self.scene.area_ellipseItem = False if self.scene.polyItem: self.scene.removeItem(self.scene.polyItem) self.scene.polyItem = False if intersect: #indicate intersect point p = QtCore.QPointF(xi, yi) self.scene.area_ellipseItem = QGraphicsEllipseItem(0, 0, 10, 10) self.scene.area_ellipseItem.setPos(p.x() - 10 / 2, p.y() - 10 / 2) self.scene.area_ellipseItem.setBrush( QtGui.QBrush(QtCore.QtColor('blue'))) #, style=QtCore.Qt.BrushStyle.SolidPattern)) self.scene.area_ellipseItem.setFlag( QGraphicsItem.GraphicsItemFlag.ItemIgnoresTransformations, False) #size stays small, but doesnt translate if set to false self.scene.addItem(self.scene.area_ellipseItem) #shade polygon region points = [ QtCore.QPointF(x,y) for x,y in zip( self.A.x[k:], self.A.y[k:] ) ] points.append(QtCore.QPointF(xi,yi)) self.scene.polyItem = QGraphicsPolygonItem(QtGui.QPolygonF(points)) self.scene.polyItem.setBrush( QtGui.QBrush(QtGui.QColor(255,255,255,127)) ) self.scene.addItem(self.scene.polyItem) self.scene.testline = QGraphicsLineItem(QtCore.QLineF(start, end)) self.scene.addItem(self.scene.testline)