def xsectArcRect1(arc, rect): """Find the single intersection point of the arc and the rectangle. arc -- Arc rect -- QRectF The arc start point is assumed to be at the center of the rect. Return a QPointF if the arc exits the rect exactly once and does not re-enter the rect. Else return None. """ # points where the line SEGMENT and the arc SEGMENT intersect xsectPoints = [] tl = rect.topLeft() tr = rect.topRight() bl = rect.bottomLeft() br = rect.bottomRight() cx = arc.centerX() cy = arc.centerY() r = arc.radius() for l in [QLineF(tl, tr), QLineF(tr, br), QLineF(br, bl), QLineF(bl, tl)]: for x, y in xsectLineCir(l, cx, cy, r): p = QPointF(x, y) if isPointOnArc(p, arc.center(), arc.start(), arc.span()): if isPointOnLineSeg(p, l): xsectPoints.append(p) if len(xsectPoints) == 1: return xsectPoints[0] else: return None
def setLine(self, line): """ Set the arrow base line (a `QLineF` in object coordinates). """ if self.__line != line: self.__line = line # local item coordinate system geom = self.geometry().translated(-self.pos()) if geom.isNull() and not line.isNull(): geom = QRectF(0, 0, 1, 1) arrow_shape = arrow_path_concave(line, self.lineWidth()) arrow_rect = arrow_shape.boundingRect() if not (geom.contains(arrow_rect)): geom = geom.united(arrow_rect) if self.__autoAdjustGeometry: # Shrink the geometry if required. geom = geom.intersected(arrow_rect) # topLeft can move changing the local coordinates. diff = geom.topLeft() line = QLineF(line.p1() - diff, line.p2() - diff) self.__arrowItem.setLine(line) self.__line = line # parent item coordinate system geom.translate(self.pos()) self.setGeometry(geom)
def plot_vert_line_graph(self, qp, x_line, color, c, arrow_up=False, arrow_down=False): if x_line < self._start_date or x_line > self._end_date: return x_line -= self._start_date qp.save() qp.setPen(color) qp.setBrush(color) qp.setRenderHint(QPainter.Antialiasing) arrowSize = 2.0 x, y = self.origGraph(c) line = QLineF(x + self.convX(x_line), y + 10, x + self.convX(x_line), y + 50) qp.drawLine(line) if arrow_up: arrowP1 = line.p1() + QPointF(arrowSize, arrowSize * 3) arrowP2 = line.p1() + QPointF(-arrowSize, arrowSize * 3) qp.drawLine(line.p1(), arrowP1) qp.drawLine(line.p1(), arrowP2) if arrow_down: arrowP1 = line.p2() + QPointF(arrowSize, - arrowSize * 3) arrowP2 = line.p2() + QPointF(-arrowSize, - arrowSize * 3) qp.drawLine(line.p2(), arrowP1) qp.drawLine(line.p2(), arrowP2) qp.restore()
def __drawLine(self, value, duration, printvalue=True): ''' Draws a line depending on the type of the waveform. @param value: value to add to wave @param duration: integer, defines duration(length) of value in wave @param printvalue: bool, add values to waveform (for value-type waveforms only) ''' self.width = self.width + duration tmp = self.curPos self.curPos = QPointF(self.curPos.x() + duration, self.curPos.y()) if self.type == "bool": if value: self.addItem(QtGui.QGraphicsLineItem(QLineF(tmp, self.curPos))) else: self.addItem( QtGui.QGraphicsLineItem(tmp.x(), tmp.y() + self.vSpace, self.curPos.x(), self.curPos.y() + self.vSpace)) elif self.type in self.supportedTypes: if printvalue: text = QtGui.QGraphicsTextItem(str(value)) text.setFont(self.valFont) text.setDefaultTextColor(self.valFontColor) text.setPos(QPointF(tmp.x() + 4, tmp.y() - 5)) self.addItem(text) self.addItem(QtGui.QGraphicsLineItem(QLineF(tmp, self.curPos))) self.addItem( QtGui.QGraphicsLineItem(tmp.x(), tmp.y() + self.vSpace, self.curPos.x(), self.curPos.y() + self.vSpace))
def paint(self, painter, option, widget=None): painter.setPen(self.pen()) if not self.__arrowed: headCenter = self.mapFromItem(self.__head[ENode.kGuiAttributeParent], self.__head[ENode.kGuiAttributeParent].boundingRect().center()) tailCenter = self.mapFromItem(self.__tail[ENode.kGuiAttributeParent], self.__tail[ENode.kGuiAttributeParent].boundingRect().center()) centerPoint = QLineF(headCenter, tailCenter).pointAt(0.5) centerPoint.setX(self.__headOffsetLine.p2().x()) centerPoint.setX(self.__tailOffsetLine.p2().x()) painter.drawPath(self.drawPath(self.__headOffsetLine.p1(), self.__tailOffsetLine.p1())[0]) else: painter.drawLine(self.__line) painter.setPen(Qt.NoPen) painter.setBrush(QColor(43, 43, 43)) headCutPoint = self.getIntersectPoint(self.__head[ENode.kGuiAttributeParent].Polygon, self.__line.p1(), self.__line.p2()) tailCutPoint = self.getIntersectPoint(self.__tail[ENode.kGuiAttributeParent].Polygon, self.__line.p2(), self.__line.p1()) painter.drawPolygon(self.getArrow(QLineF(headCutPoint, tailCutPoint)))
def test_arrowannotation(self): item = ArrowItem() self.scene.addItem(item) item.setLine(QLineF(100, 100, 100, 200)) item.setLineWidth(5) item = ArrowItem() item.setLine(QLineF(150, 100, 150, 200)) item.setLineWidth(10) item.setArrowStyle(ArrowItem.Concave) self.scene.addItem(item) item = ArrowAnnotation() item.setPos(10, 10) item.setLine(QLineF(10, 10, 200, 200)) self.scene.addItem(item) item.setLineWidth(5) def advance(): clock = time.clock() * 10 item.setLineWidth(5 + math.sin(clock) * 5) item.setColor(QColor(Qt.red).lighter(100 + 30 * math.cos(clock))) self.singleShot(0, advance) advance() self.app.exec_()
def paint(self, painter, option, widget=None): painter.setPen(EDraw.EColor.DefaultEnterHoverPen) lineX = QLineF(QPointF(self.__gridSize, 0.0), QPointF(0.0, 0.0)).translated(-self.scenePos()) lineY = QLineF(QPointF(0.0, -self.__gridSize), QPointF(0.0, 0.0)).translated(-self.scenePos()) painter.drawLines([lineX, lineY]) self.__snapPoint = QPointF(self.__gridSize * round(self.scenePos().x() / self.__gridSize), self.__gridSize * round(self.scenePos().y() / self.__gridSize)) if self.__isSnapMode: painter.drawPolygon(self.__polygon.translated(self.__snapPoint - self.scenePos())) self.__angle = 0.0 if self.__editPointOne is not None: painter.drawPolygon(EDraw.Circle(20, 24).translated(-(self.scenePos()) + self.__BBTemp)) painter.drawLine(QLineF(QPointF(-(self.scenePos()) + self.__BBTemp), QPointF(0.0, 0.0))) dummyLine = QLineF(QPointF(-(self.scenePos()) + self.__BBTemp), QPointF(0.0, 0.0)) painter.drawLine(QLineF(ETransform.rotatePoint(20, dummyLine.angle() + 180), QPointF()).translated(-(self.scenePos()) + self.__BBTemp)) painter.drawLine(QLineF(ETransform.rotatePoint(20, dummyLine.angle() + 360), QPointF()).translated(-(self.scenePos()) + self.__BBTemp)) self.__angle = dummyLine.angle() painter.drawPolygon(self.__polygon) painter.drawLine(self.__dummyLine)
def initShape(self): self.initHeads() #Line decoration offsetLine = QGraphicsLineItem(QLineF(90, 0, 90, 700)) asciiLine = QGraphicsLineItem(QLineF(480, 0, 480, 700)) #Add to scene self.__scene.addItem(offsetLine) self.__scene.addItem(asciiLine)
def boundingRect(self): if self._line is None: if self._orientation == Qt.Vertical: self._line = QLineF(0, self._value, self._length, self._value) else: self._line = QLineF(self._value, 0, self._value, self._length) r = QRectF(self._line.p1(), self._line.p2()) penw = self.pen().width() return r.adjusted(-penw, -penw, penw, penw)
def generate_lines(self, line, steps=4, smooth=0.7, dampen=1.0): if steps <= 0: return [line] mid = (line.p1() + line.p2()) * 0.5 diff = (line.p2() - line.p1()) norm = QPointF(-diff.y(), diff.x()) mid += norm * (random.random() - 0.5) * smooth return self.generate_lines(QLineF( line.p1(), mid), steps - 1, smooth * dampen) + self.generate_lines( QLineF(mid, line.p2()), steps - 1, smooth * dampen)
def draw_arrow(self, line, width, color): (x1, y1), (x2, y2) = line # compute points line = QLineF(x1, y1, x2, y2) # If the line is very small, we make our arrowhead smaller arrowsize = min(14, line.length()) lineangle = radians(line.angle()) arrowpt1 = line.p2() + QPointF(sin(lineangle - (pi/3)) * arrowsize, cos(lineangle - (pi/3)) * arrowsize) arrowpt2 = line.p2() + QPointF(sin(lineangle - pi + (pi/3)) * arrowsize, cos(lineangle - pi + (pi/3)) * arrowsize) head = QPolygonF([line.p2(), arrowpt1, arrowpt2]) # We have to draw the actual line a little short for the tip of the arrowhead not to be too wide adjustedLine = QLineF(line) adjustedLine.setLength(line.length() - arrowsize/2) # draw line painter = self.current_painter color = COLORS[color] painter.save() pen = QPen(painter.pen()) pen.setColor(color) pen.setWidthF(width) painter.setPen(pen) painter.drawLine(adjustedLine) # draw arrowhead painter.setPen(Qt.NoPen) brush = painter.brush() brush.setColor(color) brush.setStyle(Qt.SolidPattern) painter.setBrush(brush) painter.drawPolygon(head) painter.restore()
def __activeControlMoved(self, pos): line = QLineF(self.__line) control = self.__activeControl if control.anchor() == ControlPoint.TopLeft: line.setP1(pos) elif control.anchor() == ControlPoint.BottomRight: line.setP2(pos) if self.__line != line: self.blockSignals(True) self.setLine(line) self.blockSignals(False) self.lineEdited.emit(line)
def setHeads(self, pagesPerBlock): if self.heditor.pageOffView: self.setOffsetHead() else: self.setBlockHead() self.setPageHead(self.heditor.pagesPerBlock) linesize = 95 + (self.heditor.pagesPerBlock * (self.pagew + 2)) #Decoration headLine = QGraphicsLineItem(QLineF(0, 20, linesize, 20)) self.scene.addItem(headLine) headOffLine = QGraphicsLineItem(QLineF(90, 0, 90, 700)) self.scene.addItem(headOffLine)
def qpainterpath_simple_split(path, t): """ Split a QPainterPath defined simple curve. The path must be either empty or composed of a single LineToElement or CurveToElement. Parameters ---------- path : QPainterPath t : float Point where to split specified as a percentage along the path Returns ------- splitpath: Tuple[QPainterPath, QPainterPath] A pair of QPainterPaths """ assert path.elementCount() > 0 el0 = path.elementAt(0) assert el0.type == QPainterPath.MoveToElement if path.elementCount() == 1: p1 = QPainterPath() p1.moveTo(el0.x, el0.y) return p1, QPainterPath(p1) el1 = path.elementAt(1) if el1.type == QPainterPath.LineToElement: pointat = path.pointAtPercent(t) l1 = QLineF(el0.x, el0.y, pointat.x(), pointat.y()) l2 = QLineF(pointat.x(), pointat.y(), el1.x, el1.y) p1 = QPainterPath() p2 = QPainterPath() p1.addLine(l1) p2.addLine(l2) return p1, p2 elif el1.type == QPainterPath.CurveToElement: c0, c1, c2, c3 = el0, el1, path.elementAt(2), path.elementAt(3) assert all(el.type == QPainterPath.CurveToDataElement for el in [c2, c3]) cp = [QPointF(el.x, el.y) for el in [c0, c1, c2, c3]] first, second = bezier_subdivide(cp, t) p1, p2 = QPainterPath(), QPainterPath() p1.moveTo(first[0]) p1.cubicTo(*first[1:]) p2.moveTo(second[0]) p2.cubicTo(*second[1:]) return p1, p2 else: assert False
def drawAxis(self, painter, rect, axis): """ Draws the axis for the given painter. :param painter | <QPainter> rect | <QRect> """ if not axis: return # draw the axis lines painter.save() pen = QPen(self.axisColor()) pen.setWidth(3) painter.setPen(pen) # draw the vertical line if axis.orientation() == Qt.Vertical: line = QLineF(rect.right(), rect.top(), rect.right(), rect.bottom()) painter.drawLine(line) painter.setFont(axis.labelFont()) for y, height, label in self._buildData.get('grid_h_labels', []): painter.drawText(0, y - height / 2.0, rect.width() - 3, height, Qt.AlignRight | Qt.AlignVCenter, label) painter.translate(0, rect.center().y()) painter.rotate(-90) painter.setFont(axis.titleFont()) painter.drawText(-rect.height() / 2, 0, rect.height(), rect.width(), Qt.AlignHCenter | Qt.AlignTop, axis.title()) # draw the horizontal line else: line = QLineF(rect.left(), rect.top(), rect.right(), rect.top()) painter.setFont(axis.titleFont()) painter.drawText(rect, Qt.AlignHCenter | Qt.AlignBottom, axis.title()) painter.drawLine(line) painter.setFont(axis.labelFont()) for x, width, label in self._buildData.get('grid_v_labels', []): painter.drawText(x - width / 2.0, 3, width, rect.height() - 6, Qt.AlignHCenter | Qt.AlignTop, label) painter.restore()
def _updateTextAnchors(self): n = len(self._items) items = self._items dist = 15 shape = reduce(QPainterPath.united, [item.path() for item in items]) brect = shape.boundingRect() bradius = max(brect.width() / 2, brect.height() / 2) center = self.boundingRect().center() anchors = _category_anchors(items) self._textanchors = [] for angle, anchor_h, anchor_v in anchors: line = QLineF.fromPolar(bradius, angle) ext = QLineF.fromPolar(dist, angle) line = QLineF(line.p1(), line.p2() + ext.p2()) line = line.translated(center) anchor_pos = line.p2() self._textanchors.append((anchor_pos, anchor_h, anchor_v)) for i in range(n): self._updateTextItemPos(i)
def shape_line_intersection(shape, shape_pos, line): """ Return point of intersection between shape and line that is closest to line.p1(). """ intersections, point = [], QPointF() p1 = shape.pointAtPercent(0) + shape_pos r = shape.boundingRect() for t in np.linspace(0, 1.01, 50) % 1: p2 = shape.pointAtPercent(t) + shape_pos if QLineF(p1, p2).intersect(line, point) == QLineF.BoundedIntersection: intersections.append(QPointF(point)) p1 = p2 return min(intersections, key=lambda point: QLineF(line.p1(), point).length())
def paint(self, painter): pen = QPen(Qt.black) pen.setWidthF(2.5) painter.setPen(pen) line = QLineF(self.startPoint, self.pos) painter.drawLine(line) if self.pos != self.startPoint: #draw arrowhead a = line.angle() l1 = QLineF.fromPolar(25, a - 155) l1.translate(self.pos) l2 = QLineF.fromPolar(25, a + 155) l2.translate(self.pos) painter.drawLine(l1) painter.drawLine(l2)
def update(self): QGraphicsObject.prepareGeometryChange(self) self.__headPoint = self.mapFromItem(self.__head[ENode.kGuiAttributeParent], self.__head[ENode.kGuiAttributePlug]) self.__tailPoint = self.mapFromItem(self.__tail[ENode.kGuiAttributeParent], self.__tail[ENode.kGuiAttributePlug]) self.__headOffsetLine = QLineF(self.__headPoint, QPointF(self.__headPoint.x() + 15, self.__headPoint.y())) self.__tailOffsetLine = QLineF(self.__tailPoint, QPointF(self.__tailPoint.x() - 15, self.__tailPoint.y())) line = QLineF(self.__headPoint, self.__tailPoint) self.__line = line
def getPoints(self, count, opposite=False): result = [] line = QLineF(self.__polygon.boundingRect().topLeft(), self.__polygon.boundingRect().topRight()) if opposite: line = QLineF(self.__polygon.boundingRect().bottomLeft(), self.__polygon.boundingRect().bottomRight()) step = 1.0 / (count + 1) currentStep = step for x in range(0, count): result.append(line.pointAt(currentStep)) currentStep += step return result
def draw_axes(self): self.remove_all_axes() for i in range(len(self.attributes)): axis_id = UserAxis + i a = self.add_axis(axis_id, line=QLineF(i, 0, i, 1), arrows=AxisStart | AxisEnd, zoomable=True) a.always_horizontal_text = True a.max_text_width = 100 a.title_margin = -10 a.text_margin = 0 a.setZValue(5) self.set_axis_title(axis_id, self.data_domain[self.attributes[i]].name) self.set_show_axis_title(axis_id, self.show_attr_values) if self.show_attr_values: attr = self.data_domain[self.attributes[i]] if attr.is_continuous: self.set_axis_scale(axis_id, self.attr_values[attr.name][0], self.attr_values[attr.name][1]) elif attr.is_discrete: attribute_values = get_variable_values_sorted( self.data_domain[self.attributes[i]]) attr_len = len(attribute_values) values = [ float(1.0 + 2.0 * j) / float(2 * attr_len) for j in range(len(attribute_values)) ] a.set_bounds((0, 1)) self.set_axis_labels(axis_id, labels=attribute_values, values=values)
def __on_lineGeometryChanged(self): # Possible geometry change from out of our control, for instance # item move as a part of a selection group. if not self.control.isControlActive(): line = self.item.line() p1, p2 = map(self.item.mapToScene, (line.p1(), line.p2())) self.control.setLine(QLineF(p1, p2))
def paint( self, painter, option, widget=None ): if self.visible == True: painter.setPen( QColor( self.color ) ) # see try-catch (pardon me) above try: self.sp = CST.toCcsCoord( self.ccs, self.startPoint.x, self.startPoint.y ) self.ep = CST.toCcsCoord( self.ccs, self.endPoint.x, self.endPoint.y ) except: self.sp = CST.toCcsCoord( self.ccs, self.startPoint.x(), self.startPoint.y() ) self.ep = CST.toCcsCoord( self.ccs, self.endPoint.x(), self.endPoint.y() ) self.Rect = QRectF( self.sp, self.ep ) self.line = QLineF( self.sp, self.ep ) if self.line.length() > self.minLength or self.drawAlways == True: painter.drawLine( self.line ) if self.paintToBorder == True: # paint line to approximately the edge of the ccs. ep2 = self.line.pointAt( self.ccs.width / self.line.length() * 2) painter.drawLine(self.ep,ep2) sp2 = self.line.pointAt(-self.ccs.width / self.line.length() * 2) painter.drawLine(self.sp,sp2) if self.showIncline == True: incline = ( self.endPoint.y - self.startPoint.y ) / ( self.endPoint.x - self.startPoint.x ) # print text limited to 2 decimal digits. painter.setBackground ( QBrush ( QColor( 'lightGrey' ) ) ) painter.setBackgroundMode (Qt.BGMode(1)) painter.setPen( QColor( 'black' ) )
def line_extended(line, distance): """ Return an QLineF extended by `distance` units in the positive direction. """ angle = line.angle() / 360 * 2 * math.pi dx, dy = unit_point(angle, r=distance) return QLineF(line.p1(), line.p2() + QPointF(dx, dy))
def drawOneLine(self, timeChecked, occ): if not self.timeline.selDateMin: dateMin = self.timeline.baseDateMin dateMax = self.timeline.baseDateMax maxOcc = self.timeline.maxOcc else: dateMin = self.timeline.selDateMin dateMax = self.timeline.selDateMax maxOcc = self.timeline.maxOccZoom if (dateMax - dateMin) > 0: x = ((timeChecked - dateMin) * (self.ploter.width - self.m - self.yLeftMargin)) / ( dateMax - dateMin) + self.yLeftMargin y = (((maxOcc - occ) * (self.ploter.height - self.m - (self.m / 3))) / maxOcc) + (self.m / 3) if x <= self.yLeftMargin: x += 3 startY = self.ploter.height - self.m - 1 endY = y if y < self.ploter.height - self.m - 1: # Y level to show is biggest than penWidth startY -= 1 endY -= 1 if endY <= self.m / 3: # Y level is biggest than Y max value endY = self.m / 3 + 2 line = QLineF(x, startY, x, endY) self.painter.drawLines(line)
def __init__(self, parent=None, line=None, **kwargs): Annotation.__init__(self, parent, **kwargs) self.setFlag(QGraphicsItem.ItemIsMovable) self.setFlag(QGraphicsItem.ItemIsSelectable) self.setFocusPolicy(Qt.ClickFocus) if line is None: line = QLineF(0, 0, 20, 0) self.__line = line self.__color = QColor(Qt.red) self.__arrowItem = ArrowItem(self) self.__arrowItem.setLine(line) self.__arrowItem.setBrush(self.__color) self.__arrowItem.setPen(QPen(Qt.NoPen)) self.__arrowItem.setArrowStyle(ArrowItem.Concave) self.__arrowItem.setLineWidth(5) self.__shadow = QGraphicsDropShadowEffect( blurRadius=5, offset=QPointF(1.0, 2.0), ) self.__arrowItem.setGraphicsEffect(self.__shadow) self.__shadow.setEnabled(True) self.__autoAdjustGeometry = True
def paint(self, painter, option, widget=None): bounds = self.bounds for x in range(0, int(bounds.width()), self.size): self.lines.append( QLineF(x, bounds.y(), x, bounds.y() + bounds.height())) for y in range(0, int(bounds.height()), self.size): self.lines.append( QLineF(bounds.x(), y, bounds.x() + bounds.width(), y)) painter.setPen(self.pen) for line in self.lines: painter.drawLine(line)
def initHeads(self): self.offHead = QGraphicsTextItem() self.hexHead = QGraphicsTextItem() self.asciiHead = QGraphicsTextItem() #Set Color self.offHead.setDefaultTextColor(QColor(Qt.red)) self.hexHead.setDefaultTextColor(QColor(Qt.black)) self.asciiHead.setDefaultTextColor(QColor(Qt.darkCyan)) #Create Font self.font = QFont("Gothic") self.font.setFixedPitch(1) self.font.setBold(False) self.font.setPixelSize(14) #Set Font self.offHead.setFont(self.font) self.hexHead.setFont(self.font) self.asciiHead.setFont(self.font) #Set Text self.offHead.setPlainText("Offset") self.hexHead.setPlainText( "0 1 2 3 4 5 6 7 8 9 A B C D E F") self.asciiHead.setPlainText("Ascii") #Position self.offHead.setPos(20, 0) self.hexHead.setPos(95, 0) self.asciiHead.setPos(520, 0) #Add to scene self.__scene.addItem(self.offHead) self.__scene.addItem(self.hexHead) self.__scene.addItem(self.asciiHead) headLine = QGraphicsLineItem(QLineF(0, 20, 615, 20)) self.__scene.addItem(headLine)
def paint(self, painter, option, index): curr_class_dist = np.array(index.data(Qt.DisplayRole), dtype=float) curr_class_dist /= sum(curr_class_dist) painter.save() self.drawBackground(painter, option, index) rect = option.rect if sum(curr_class_dist) > 0: pw = 3 hmargin = 5 x = rect.left() + hmargin width = rect.width() - 2 * hmargin vmargin = 1 textoffset = pw + vmargin * 2 painter.save() baseline = rect.bottom() - textoffset / 2 text = str(index.data(Qt.DisplayRole)) option.displayAlignment = Qt.AlignCenter text_rect = rect.adjusted(0, 0, 0, -textoffset * 0) self.drawDisplay(painter, option, text_rect, text) painter.setRenderHint(QPainter.Antialiasing) for prop, color in zip(curr_class_dist, self.color_schema): if prop == 0: continue painter.setPen(QPen(QBrush(color), pw)) to_x = x + prop * width line = QLineF(x, baseline, to_x, baseline) painter.drawLine(line) x = to_x painter.restore() painter.restore()
def arrow_path_concave(line, width): """ Return a :class:`QPainterPath` of a pretty looking arrow. """ path = QPainterPath() p1, p2 = line.p1(), line.p2() if p1 == p2: return path baseline = QLineF(line) # Require some minimum length. baseline.setLength(max(line.length() - width * 3, width * 3)) start, end = baseline.p1(), baseline.p2() mid = (start + end) / 2.0 normal = QLineF.fromPolar(1.0, baseline.angle() + 90).p2() path.moveTo(start) path.lineTo(start + (normal * width / 4.0)) path.quadTo(mid + (normal * width / 4.0), end + (normal * width / 1.5)) path.lineTo(end - (normal * width / 1.5)) path.quadTo(mid - (normal * width / 4.0), start - (normal * width / 4.0)) path.closeSubpath() arrow_head_len = width * 4 arrow_head_angle = 50 line_angle = line.angle() - 180 angle_1 = line_angle - arrow_head_angle / 2.0 angle_2 = line_angle + arrow_head_angle / 2.0 points = [p2, p2 + QLineF.fromPolar(arrow_head_len, angle_1).p2(), baseline.p2(), p2 + QLineF.fromPolar(arrow_head_len, angle_2).p2(), p2] poly = QPolygonF(points) path_head = QPainterPath() path_head.addPolygon(poly) path = path.united(path_head) return path
def getIntersectPoint(self, polygon, point1, point2): p1 = polygon[0] + point1 intersectPoint = QPointF() for i in polygon: p2 = i + point2 polyLine = QLineF(p1, p2) intersectType = polyLine.intersect(QLineF(point1, point2), intersectPoint) if intersectType == QLineF.BoundedIntersection: break p1 = p2 return intersectPoint
class MyArrow(QGraphicsLineItem): def __init__(self): super(MyArrow, self).__init__() self.source = QPointF(0, 250) self.dest = QPointF(120, 120) self.line = QLineF(self.source, self.dest) self.line.setLength(self.line.length() - 20) def paint(self, QPainter, QStyleOptionGraphicsItem, QWidget_widget=None): # setPen pen = QPen() pen.setWidth(5) pen.setJoinStyle(Qt.MiterJoin) #让箭头变尖 QPainter.setPen(pen) # draw line QPainter.drawLine(self.line)
def angle(point1, point2): """Return the angle between the two points in range from -180 to 180. """ angle = QLineF(point1, point2).angle() if angle > 180: return angle - 360 else: return angle
def change_selector(self): if self.d2.isChecked(): self.scan_type = "continuous" self.selector = lambda start, end: self.camera_scene.addLine( QLineF(start, end)) else: self.scan_type = "3D" self.selector = self.select_rect
def updatePosition(self, scene): pos0 = scene.posFromLonLat(self._lon0, self._lat0) pos1 = scene.posFromLonLat(self._lon1, self._lat1) deltaPos = pos1 - pos0 self.prepareGeometryChange() self.setLine(QLineF(QPointF(0.0, 0.0), deltaPos)) self.setPos(pos0)
def dummyLine(self, angle=None, length=None): if angle is not None and length is not None: pt1 = QLineF(QPointF(0.0, 0.0), QPointF(0.0, 1.0)) pt1.setAngle(angle) pt1.setLength(length + 16) self.__dummyLine = pt1 return self.__dummyLine = QLineF()
def paint(self, painter, option, widget=None): painter.setPen(self.pen()) headCenter = self.mapFromItem(self.__head[ENode.kGuiAttributeParent], self.__head[ENode.kGuiAttributeParent].boundingRect().center()) tailCenter = self.mapFromItem(self.__tail[ENode.kGuiAttributeParent], self.__tail[ENode.kGuiAttributeParent].boundingRect().center()) centerPoint = QLineF(headCenter, tailCenter).pointAt(0.5) centerPoint.setX(self.__headOffsetLine.p2().x()) lineFromHead = QLineF(self.__headOffsetLine.p2(), centerPoint) centerPoint.setX(self.__tailOffsetLine.p2().x()) lineFromTail = QLineF(self.__tailOffsetLine.p2(), centerPoint) painter.drawPath(self.drawPath(self.__headOffsetLine.p1(), self.__tailOffsetLine.p1())[0])
def update_ends(self): try: self.prepareGeometryChange() self.setLine( QLineF(self.node1.edge_out_point(self), self.node2.edge_in_point(self))) except RuntimeError: # this gets called through QTimer.singleShot # and might already be deleted by Qt pass
def _setup_plot(self): self.__replot_requested = False self.clear_plot() variables = list(self.varmodel_selected) if not variables: return coords = [self._get_data(var) for var in variables] coords = numpy.vstack(coords) p, N = coords.shape assert N == len(self.data), p == len(variables) axes = linproj.defaultaxes(len(variables)) assert axes.shape == (2, p) mask = ~numpy.logical_or.reduce(numpy.isnan(coords), axis=0) coords = coords[:, mask] X, Y = numpy.dot(axes, coords) X = plotutils.normalized(X) Y = plotutils.normalized(Y) pen_data, brush_data = self._color_data(mask) size_data = self._size_data(mask) shape_data = self._shape_data(mask) if self.jitter_value > 0: value = [0, 0.01, 0.1, 0.5, 1, 2][self.jitter_value] rstate = numpy.random.RandomState(0) jitter_x = (rstate.random_sample(X.shape) * 2 - 1) * value / 100 rstate = numpy.random.RandomState(1) jitter_y = (rstate.random_sample(Y.shape) * 2 - 1) * value / 100 X += jitter_x Y += jitter_y self._item = ScatterPlotItem( X, Y, pen=pen_data, brush=brush_data, size=size_data, shape=shape_data, antialias=True, data=numpy.arange(len(self.data))[mask] ) self._item._mask = mask self.viewbox.addItem(self._item) for i, axis in enumerate(axes.T): axis_item = AxisItem(line=QLineF(0, 0, axis[0], axis[1]), label=variables[i].name) self.viewbox.addItem(axis_item) self.viewbox.setRange(QtCore.QRectF(-1.05, -1.05, 2.1, 2.1))
def __init__(self): QGraphicsObject.__init__(self) self.__uuid = uuid.uuid1() #self.setZValue(-0.5) self.__polygon = EDraw.Circle(7, 12) self.__isSnapMode = False self.__snapPoint = QPointF(0.0, 0.0) self.__gridSize = 10 self.__dummyLine = QLineF() self.__dummyData = None self.__editPointOne = None self.__BBTemp = None self.__angle = 0.0
def calculateForces(self): if not self.scene() or self.scene().mouseGrabberItem() is self: self.newPos = self.pos() return # Sum up all forces pushing this item away. xvel = 0.0 yvel = 0.0 for item in self.scene().items(): if not isinstance(item, Node): continue line = QLineF(self.mapFromItem(item, 0, 0), QPointF(0, 0)) dx = line.dx() dy = line.dy() l = 2.0 * (dx * dx + dy * dy) if l > 0: xvel += (dx * 150.0) / l yvel += (dy * 150.0) / l # Now subtract all forces pulling items together. #weight = (len(self.edgeList) + 1) * 100.0 for edge in self.edgeList: if edge.sourceNode() is self: pos = self.mapFromItem(edge.destNode(), 0, 0) else: weight = edge.weight * 6 pos = self.mapFromItem(edge.sourceNode(), 0, 0) xvel += pos.x() / weight yvel += pos.y() / weight if qAbs(xvel) < 0.1 and qAbs(yvel) < 0.1: xvel = yvel = 0.0 sceneRect = self.scene().sceneRect() self.newPos = self.pos() + QPointF(xvel, yvel) self.newPos.setX( min(max(self.newPos.x(), sceneRect.left() + 10), sceneRect.right() - 10)) self.newPos.setY( min(max(self.newPos.y(), sceneRect.top() + 10), sceneRect.bottom() - 10))
def drawPath(self, startPoint, endPoint): path = QPainterPath() one = (QPointF(endPoint.x(), startPoint.y()) + startPoint) / 2 two = (QPointF(startPoint.x(), endPoint.y()) + endPoint) / 2 path.moveTo(startPoint) if startPoint.x() > endPoint.x(): dist = (startPoint.x() - endPoint.x()) * 2 tLine = QLineF((dist / 2), 0.0, -(dist / 2), 0.0).translated(QLineF(startPoint, endPoint).pointAt(0.5)) one = tLine.p1() two = tLine.p2() path.cubicTo(one, two, endPoint) self.__path = path return path, QLineF(one, two)
def paint(self, painter, option, widget=None): color, _ = Edge.Color.SELECTED if self.selected else Edge.Color.DEFAULT pen = self.pen() pen.setColor(color) pen.setBrush(QBrush(color)) pen.setWidth(np.clip(2 * self.weight(), .5, 4)) painter.setPen(pen) self.setPen(pen) if self.source == self.dest: return self.paintArc(painter, option, widget) if self.source.collidesWithItem(self.dest): return have_two_edges = len([edge for edge in self.source.edges if self.source in edge and self.dest in edge and edge is not self]) source_pos = self.source.pos() dest_pos = self.dest.pos() color = self.pen().color() painter.setBrush(color) point = shape_line_intersection(self.dest.shape(), dest_pos, QLineF(source_pos, dest_pos)) line = QLineF(source_pos, point) if have_two_edges: normal = line.normalVector() normal.setLength(15) line = QLineF(normal.p2(), point) self.label.setPos(line.pointAt(.5)) self.squares.placeBelow(self.label) self.setLine(line) painter.drawLine(line) # Draw arrow head self.arrowHead.clear() for point in self._arrowhead_points(line): self.arrowHead.append(point) painter.drawPolygon(self.arrowHead)
def __init__(self, parent=None, line=None, label=None, **kwargs): super().__init__(parent, **kwargs) self.setFlag(pg.GraphicsObject.ItemHasNoContents) if line is None: line = QLineF(0, 0, 1, 0) self._spine = QGraphicsLineItem(line, self) angle = QLineF(0, 0, 1, 0).angleTo(line) angle = (180 - angle) % 360 dx = line.x2() - line.x1() dy = line.y2() - line.y1() rad = numpy.arctan2(dy, dx) angle = (rad * 180 / numpy.pi) % 360 self._arrow = pg.ArrowItem(parent=self, angle=180 - angle) self._arrow.setPos(self._spine.line().p2()) self._label = pg.TextItem(text=label, color=(10, 10, 10)) self._label.setParentItem(self) self._label.setPos(self._spine.line().p2())
def start_end(self): line_start = QLineF(self) line_end = QLineF(self.p2(), self.p1()) line_start.setLength(30) line_end.setLength(30) return line_start, line_end
def overlay_for(pt1, pt2, frequency): # Construct the line-geometry, we'll use this to construct the ellipsoid line = QLineF(pt1, pt2) # Determine the radius for the ellipsoid radius = fresnel_radius(line.length(), frequency) # Draw the ellipsoid zone = QPainterPath() zone.addEllipse(QPointF(0., 0.), line.length() / 2, radius) # Rotate the ellipsoid - same angle as the line transform = QTransform() transform.rotate(-line.angle()) zone = transform.map(zone) # Center the zone over the line lc = QRectF(pt1, pt2).center() zc = zone.boundingRect().center() zone.translate(lc.x() - zc.x(), lc.y() - zc.y()) return line, zone
def getLines(self, count, opposite=False): angleOffset = 25 inputLines = [] startAngle = QLineF(QPointF(0.0, 0.0), self.boundingRect().topRight()).angle() + angleOffset endAngle = QLineF(QPointF(0.0, 0.0), self.boundingRect().topLeft()).angle() - angleOffset if opposite: startAngle = QLineF(QPointF(0.0, 0.0), self.boundingRect().bottomLeft()).angle() + angleOffset endAngle = QLineF(QPointF(0.0, 0.0), self.boundingRect().bottomRight()).angle() - angleOffset step = (endAngle - startAngle) / (count - 1) for x in range(0, count): tLine = QLineF(QPointF(0.0, 0.0), QPointF(0, 100)) tLine.setAngle(startAngle) inputLines.append(tLine) startAngle += step return inputLines
def adjustGeometry(self): """ Adjust the widget geometry to exactly fit the arrow inside while preserving the arrow path scene geometry. """ # local system coordinate geom = self.geometry().translated(-self.pos()) line = self.__line arrow_rect = self.__arrowItem.shape().boundingRect() if geom.isNull() and not line.isNull(): geom = QRectF(0, 0, 1, 1) if not (geom.contains(arrow_rect)): geom = geom.united(arrow_rect) geom = geom.intersected(arrow_rect) diff = geom.topLeft() line = QLineF(line.p1() - diff, line.p2() - diff) geom.translate(self.pos()) self.setGeometry(geom) self.setLine(line)
def __init__(self, parent=None, orientation=Qt.Vertical, value=0.0, length=10.0, **kwargs): self._orientation = orientation self._value = value self._length = length self._min = 0.0 self._max = 1.0 self._line = QLineF() self._pen = QPen() super().__init__(parent, **kwargs) self.setAcceptedMouseButtons(Qt.LeftButton) self.setPen(make_pen(brush=QColor(50, 50, 50), width=1, cosmetic=True)) if self._orientation == Qt.Vertical: self.setCursor(Qt.SizeVerCursor) else: self.setCursor(Qt.SizeHorCursor)
def __init__(self, parent=None, **kwargs): QGraphicsObject.__init__(self, parent, **kwargs) self.setFlag(QGraphicsItem.ItemHasNoContents) self.setFlag(QGraphicsItem.ItemIsFocusable) self.__line = QLineF() self.__points = \ [ControlPoint(self, ControlPoint.TopLeft), # TopLeft is line start ControlPoint(self, ControlPoint.BottomRight) # line end ] self.__activeControl = None if self.scene(): self.__installFilter() for p in self.__points: p.setFlag(QGraphicsItem.ItemIsFocusable) p.setFocusProxy(self)
def drawPath(self, startPoint, endPoint): path = QPainterPath() one = (QPointF(endPoint.x(), startPoint.y()) + startPoint) / 2 two = (QPointF(startPoint.x(), endPoint.y()) + endPoint) / 2 path.moveTo(startPoint) angle = math.pi / 2 bLine1 = QLineF() bLine1.setP1(startPoint) if startPoint.x() > endPoint.x(): dist = startPoint.x() - endPoint.x() one = (bLine1.p1() + QPointF(math.sin(angle) * dist, math.cos(angle) * dist)) bLine1.setP1(endPoint) two = (bLine1.p1() + QPointF(math.sin(angle) * dist, math.cos(angle) * dist)) path.cubicTo(one, two, endPoint) return path, QLineF(one, two)
def arrow_path_plain(line, width): """ Return an :class:`QPainterPath` of a plain looking arrow. """ path = QPainterPath() p1, p2 = line.p1(), line.p2() if p1 == p2: return path baseline = QLineF(line) # Require some minimum length. baseline.setLength(max(line.length() - width * 3, width * 3)) path.moveTo(baseline.p1()) path.lineTo(baseline.p2()) stroker = QPainterPathStroker() stroker.setWidth(width) path = stroker.createStroke(path) arrow_head_len = width * 4 arrow_head_angle = 50 line_angle = line.angle() - 180 angle_1 = line_angle - arrow_head_angle / 2.0 angle_2 = line_angle + arrow_head_angle / 2.0 points = [ p2, p2 + QLineF.fromPolar(arrow_head_len, angle_1).p2(), p2 + QLineF.fromPolar(arrow_head_len, angle_2).p2(), p2, ] poly = QPolygonF(points) path_head = QPainterPath() path_head.addPolygon(poly) path = path.united(path_head) return path
class Line( QGraphicsLineItem ): """Defines a line by two points. If points are moved, line follows these movements.""" def __init__( self, startPoint, endPoint, ccs, paintToBorder = False, showIncline = False, color = 'orange', minLength = 0 ): super( Line, self ).__init__( ccs ) self.startPoint = startPoint self.endPoint = endPoint self.ccs = ccs self.paintToBorder = paintToBorder self.showIncline = showIncline self.color = color self.visible = True # by default we only want to draw lines if its two # defining points are not too close together self.drawAlways = False self.minLength = minLength # pixel # grmbl. Line was designed to be defined by two Point.Points. Now I want to be able to define # lines as well from QPointFs. try: self.Rect = QRectF( self.startPoint.x, self.startPoint.y, self.endPoint.x, self.endPoint.y ) except: self.Rect = QRectF( self.startPoint.x(), self.startPoint.y(), self.endPoint.x(), self.endPoint.y() ) def boundingRect( self ): return self.Rect def paint( self, painter, option, widget=None ): if self.visible == True: painter.setPen( QColor( self.color ) ) # see try-catch (pardon me) above try: self.sp = CST.toCcsCoord( self.ccs, self.startPoint.x, self.startPoint.y ) self.ep = CST.toCcsCoord( self.ccs, self.endPoint.x, self.endPoint.y ) except: self.sp = CST.toCcsCoord( self.ccs, self.startPoint.x(), self.startPoint.y() ) self.ep = CST.toCcsCoord( self.ccs, self.endPoint.x(), self.endPoint.y() ) self.Rect = QRectF( self.sp, self.ep ) self.line = QLineF( self.sp, self.ep ) if self.line.length() > self.minLength or self.drawAlways == True: painter.drawLine( self.line ) if self.paintToBorder == True: # paint line to approximately the edge of the ccs. ep2 = self.line.pointAt( self.ccs.width / self.line.length() * 2) painter.drawLine(self.ep,ep2) sp2 = self.line.pointAt(-self.ccs.width / self.line.length() * 2) painter.drawLine(self.sp,sp2) if self.showIncline == True: incline = ( self.endPoint.y - self.startPoint.y ) / ( self.endPoint.x - self.startPoint.x ) # print text limited to 2 decimal digits. painter.setBackground ( QBrush ( QColor( 'lightGrey' ) ) ) painter.setBackgroundMode (Qt.BGMode(1)) painter.setPen( QColor( 'black' ) ) #~ painter.drawText( self.ep.x() + 10, self.ep.y() + 10, QString ( '%.2f' %(incline) ) ) def setVisible( self, value ): self.visible = value def setPosition( self, startPoint, endPoint ): self.startPoint = startPoint self.endPoint = endPoint def updateYourself( self, xDelta, yDelta ): # There is no action needed, as a line gets its information # from startPoint and endPoint # Just adjust self.Rect to avoid case where line disappears mysteriously and after then, # paint() is never called again self.Rect = QRectF( self.startPoint.x, self.startPoint.y, self.endPoint.x, self.endPoint.y )