예제 #1
0
    def __updateCurve(self):
        self.prepareGeometryChange()
        if self.sourceAnchor and self.sinkAnchor:
            source_pos = self.sourceAnchor.anchorScenePos()
            sink_pos = self.sinkAnchor.anchorScenePos()
            source_pos = self.curveItem.mapFromScene(source_pos)
            sink_pos = self.curveItem.mapFromScene(sink_pos)

            # Adaptive offset for the curve control points to avoid a
            # cusp when the two points have the same y coordinate
            # and are close together
            delta = source_pos - sink_pos
            dist = math.sqrt(delta.x()**2 + delta.y()**2)
            cp_offset = min(dist / 2.0, 60.0)

            # TODO: make the curve tangent orthogonal to the anchors path.
            path = QPainterPath()
            path.moveTo(source_pos)
            path.cubicTo(source_pos + QPointF(cp_offset, 0),
                         sink_pos - QPointF(cp_offset, 0), sink_pos)

            self.curveItem.setPath(path)
            self.sourceIndicator.setPos(source_pos)
            self.sinkIndicator.setPos(sink_pos)
            self.__updateText()
        else:
            self.setHoverState(False)
            self.curveItem.setPath(QPainterPath())
예제 #2
0
    def __updateCurve(self):
        self.prepareGeometryChange()
        if self.sourceAnchor and self.sinkAnchor:
            source_pos = self.sourceAnchor.anchorScenePos()
            sink_pos = self.sinkAnchor.anchorScenePos()
            source_pos = self.curveItem.mapFromScene(source_pos)
            sink_pos = self.curveItem.mapFromScene(sink_pos)

            # Adaptive offset for the curve control points to avoid a
            # cusp when the two points have the same y coordinate
            # and are close together
            delta = source_pos - sink_pos
            dist = math.sqrt(delta.x() ** 2 + delta.y() ** 2)
            cp_offset = min(dist / 2.0, 60.0)

            # TODO: make the curve tangent orthogonal to the anchors path.
            path = QPainterPath()
            path.moveTo(source_pos)
            path.cubicTo(source_pos + QPointF(cp_offset, 0),
                         sink_pos - QPointF(cp_offset, 0),
                         sink_pos)

            self.curveItem.setPath(path)
            self.sourceIndicator.setPos(source_pos)
            self.sinkIndicator.setPos(sink_pos)
            self.__updateText()
        else:
            self.setHoverState(False)
            self.curveItem.setPath(QPainterPath())
예제 #3
0
    def __init__(self, edge, modObj):
        QGraphicsPathItem.__init__(self)
        self.__edge = edge
        self.__modObj = modObj

        startPoint = QPointF(edge.points[0][0], edge.points[0][1])
        painterPath = QPainterPath(startPoint)

        index = 1
        while index + 3 <= len(edge.points):
            painterPath.cubicTo(edge.points[index][0], edge.points[index][1],
                                edge.points[index + 1][0],
                                edge.points[index + 1][1],
                                edge.points[index + 2][0],
                                edge.points[index + 2][1])
            index = index + 3
        if index + 2 <= len(edge.points):
            painterPath.quadTo(edge.points[index + 1][0],
                               edge.points[index + 1][1],
                               edge.points[index + 2][0],
                               edge.points[index + 2][1])
            index = index + 2

        if index + 1 <= len(edge.points):
            painterPath.lineTo(edge.points[index + 1][0],
                               edge.points[index + 1][1])

        self.setPath(painterPath)
        return
예제 #4
0
    def __init__( self, edge, modObj, connObj ):
        QGraphicsPathItem.__init__( self )
        self.__edge = edge
        self.__modObj = modObj
        self.__connObj = connObj

        startPoint = QPointF( edge.points[ 0 ][ 0 ], edge.points[ 0 ][ 1 ] )
        painterPath = QPainterPath( startPoint )

        index = 1
        while index + 3 <= len( edge.points ):
            painterPath.cubicTo(edge.points[index][0],  edge.points[index][1],
                                edge.points[index+1][0],edge.points[index+1][1],
                                edge.points[index+2][0],edge.points[index+2][1])
            index = index + 3
        if index + 2 <= len( edge.points ):
            painterPath.quadTo(edge.points[index+1][0], edge.points[index+1][1],
                               edge.points[index+2][0], edge.points[index+2][1])
            index = index + 2

        if index + 1 <= len( edge.points ):
            painterPath.lineTo(edge.points[index+1][0], edge.points[index+1][1])

        lastIndex = len( edge.points ) - 1
        self.addArrow( painterPath,
                       edge.points[lastIndex-1][0],
                       edge.points[lastIndex-1][1],
                       edge.points[lastIndex][0],
                       edge.points[lastIndex][1] )

        self.setPath( painterPath )
        return
예제 #5
0
    def __init__(self, edge):
        QGraphicsPathItem.__init__(self)
        self.__edge = edge

        startPoint = QPointF(edge.points[0][0], edge.points[0][1])
        painterPath = QPainterPath(startPoint)

        index = 1
        while index + 3 <= len(edge.points):
            painterPath.cubicTo(edge.points[index][0], edge.points[index][1],
                                edge.points[index + 1][0],
                                edge.points[index + 1][1],
                                edge.points[index + 2][0],
                                edge.points[index + 2][1])
            index = index + 3
        if index + 2 <= len(edge.points):
            painterPath.quadTo(edge.points[index + 1][0],
                               edge.points[index + 1][1],
                               edge.points[index + 2][0],
                               edge.points[index + 2][1])
            index = index + 2

        if index + 1 <= len(edge.points):
            painterPath.lineTo(edge.points[index + 1][0],
                               edge.points[index + 1][1])

        if edge.head != edge.tail:
            lastIndex = len(edge.points) - 1
            self.addArrow(painterPath, edge.points[lastIndex - 1][0],
                          edge.points[lastIndex - 1][1],
                          edge.points[lastIndex][0], edge.points[lastIndex][1])

        self.setPath(painterPath)
        return
예제 #6
0
 def compute_path(self):
     p1 = self.p1 if self.p1.x() < self.p2.x() else self.p2
     p2 = self.p2 if self.p1.x() < self.p2.x() else self.p1
     path = QPainterPath()
     path.moveTo(p1)
     dx = p2.x() - p1.x()
     path.cubicTo(QPoint(p1.x() + dx / 3, p1.y()), QPoint(p2.x() - dx / 3, p2.y()), p2)
     self.__path = path
예제 #7
0
    def _updatePath(self):
        p0 = self._p0
        p1 = self._p1

        path = QPainterPath()
        path.moveTo(p0)
        dx = p1.x() - p0.x()
        x0 = p0.x() + 0.7 * dx
        x1 = p1.x() - 0.7 * dx
        path.cubicTo(QPointF(x0, p0.y()), QPointF(x1, p1.y()), p1)
        self.setPath(path)
예제 #8
0
 def rebuildSmooth( self ):
     """
     Rebuilds a smooth path based on the inputed points and set \
     parameters for this item.
     
     :return     <QPainterPath>
     """
     # collect the control points
     points = self.controlPoints()
     
     # create the path
     path = QPainterPath()
     
     if ( len(points) == 3 ):
         x0, y0 = points[0]
         x1, y1 = points[1]
         xN, yN = points[2]
         
         path.moveTo(x0, y0)
         path.quadTo(x1, y1, xN, yN)
     
     elif ( len(points) == 4 ):
         x0, y0 = points[0]
         x1, y1 = points[1]
         x2, y2 = points[2]
         xN, yN = points[3]
         
         path.moveTo(x0, y0)
         path.cubicTo(x1, y1, x2, y2, xN, yN)
         
     elif ( len(points) == 6 ):
         x0, y0 = points[0]
         x1, y1 = points[1]
         x2, y2 = points[2]
         x3, y3 = points[3]
         x4, y4 = points[4]
         xN, yN = points[5]
         
         xC      = (x2+x3) / 2.0
         yC      = (y2+y3) / 2.0
         
         path.moveTo(x0, y0)
         path.cubicTo(x1, y1, x2, y2, xC, yC)
         path.cubicTo(x3, y3, x4, y4, xN, yN)
         
     else:
         x0, y0 = points[0]
         xN, yN = points[-1]
         
         path.moveTo(x0, y0)
         path.lineTo(xN, yN)
     
     return path
예제 #9
0
    def _updatePath(self):
        p0 = self._startPos
        p1 = self._endPos
        if p0 is None or p1 is None:
            return

        path = QPainterPath()
        path.moveTo(p0)
        dx = p1.x() - p0.x()
        x0 = p0.x() + 0.7 * dx
        x1 = p1.x() - 0.7 * dx
        path.cubicTo(QPointF(x0, p0.y()), QPointF(x1, p1.y()), p1)
        self.setPath(path)
예제 #10
0
파일: linkitem.py 프로젝트: tomazc/orange3
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
예제 #11
0
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
예제 #12
0
class ParallelCoordinatesCurve(OWCurve):
    def __init__(self, n_attributes, y_values, color, name=""):
        OWCurve.__init__(self, tooltip=name)
        self._item = QGraphicsPathItem(self)
        self.path = QPainterPath()
        self.fitted = False

        self.n_attributes = n_attributes
        self.n_rows = int(len(y_values) / n_attributes)

        self.set_style(OWCurve.Lines)
        if isinstance(color, tuple):
            self.set_pen(QPen(QColor(*color)))
        else:
            self.set_pen(QPen(QColor(color)))

        x_values = list(range(n_attributes)) * self.n_rows
        self.set_data(x_values, y_values)

    def update_properties(self):
        self.redraw_path()

    def redraw_path(self):
        self.path = QPainterPath()
        for segment in self.segment(self.data()):
            if self.fitted:
                self.draw_cubic_path(segment)
            else:
                self.draw_normal_path(segment)
        self._item.setPath(self.graph_transform().map(self.path))
        self._item.setPen(self.pen())

    def segment(self, data):
        for i in range(self.n_rows):
            yield data[i * self.n_attributes:(i + 1) * self.n_attributes]

    def draw_cubic_path(self, segment):
        for (x1, y1), (x2, y2) in zip(segment, segment[1:]):
            self.path.moveTo(x1, y1)
            self.path.cubicTo(QPointF(x1 + 0.5, y1),
                              QPointF(x2 - 0.5, y2), QPointF(x2, y2))

    def draw_normal_path(self, segment):
        if not segment:
            return

        x, y = segment[0]
        self.path.moveTo(x, y)
        for x, y in segment[1:]:
            self.path.lineTo(x, y)
예제 #13
0
class ParallelCoordinatesCurve(OWCurve):
    def __init__(self, n_attributes, y_values, color, name=""):
        OWCurve.__init__(self, tooltip=name)
        self._item = QGraphicsPathItem(self)
        self.path = QPainterPath()
        self.fitted = False

        self.n_attributes = n_attributes
        self.n_rows = int(len(y_values) / n_attributes)

        self.set_style(OWCurve.Lines)
        if isinstance(color, tuple):
            self.set_pen(QPen(QColor(*color)))
        else:
            self.set_pen(QPen(QColor(color)))

        x_values = list(range(n_attributes)) * self.n_rows
        self.set_data(x_values, y_values)

    def update_properties(self):
        self.redraw_path()

    def redraw_path(self):
        self.path = QPainterPath()
        for segment in self.segment(self.data()):
            if self.fitted:
                self.draw_cubic_path(segment)
            else:
                self.draw_normal_path(segment)
        self._item.setPath(self.graph_transform().map(self.path))
        self._item.setPen(self.pen())

    def segment(self, data):
        for i in range(self.n_rows):
            yield data[i * self.n_attributes:(i + 1) * self.n_attributes]

    def draw_cubic_path(self, segment):
        for (x1, y1), (x2, y2) in zip(segment, segment[1:]):
            self.path.moveTo(x1, y1)
            self.path.cubicTo(QPointF(x1 + 0.5, y1), QPointF(x2 - 0.5, y2),
                              QPointF(x2, y2))

    def draw_normal_path(self, segment):
        if not segment:
            return

        x, y = segment[0]
        self.path.moveTo(x, y)
        for x, y in segment[1:]:
            self.path.lineTo(x, y)
예제 #14
0
    def paint(self, painter, option, widget=None):
        myPen = self.pen()
        myPen.setColor(self.myColor)
        painter.setPen(myPen)
        painter.setBrush(self.myColor)

        controlPoints = []
        endPt = self.endItem.getLinkPointForParameter(self.endIndex)
        startPt = self.startItem.getLinkPointForOutput(self.startIndex)
        if isinstance(self.startItem.element, Algorithm):
            if self.startIndex != -1:
                controlPoints.append(self.startItem.pos() + startPt)
                controlPoints.append(self.startItem.pos() + startPt +
                                     QPointF(ModelerGraphicItem.BOX_WIDTH /
                                             2, 0))
                controlPoints.append(self.endItem.pos() + endPt -
                                     QPointF(ModelerGraphicItem.BOX_WIDTH /
                                             2, 0))
                controlPoints.append(self.endItem.pos() + endPt)
                pt = QPointF(self.startItem.pos() + startPt + QPointF(-3, -3))
                painter.drawEllipse(pt.x(), pt.y(), 6, 6)
                pt = QPointF(self.endItem.pos() + endPt + QPointF(-3, -3))
                painter.drawEllipse(pt.x(), pt.y(), 6, 6)
            else:
                # Case where there is a dependency on an algorithm not
                # on an output
                controlPoints.append(self.startItem.pos() + startPt)
                controlPoints.append(self.startItem.pos() + startPt +
                                     QPointF(ModelerGraphicItem.BOX_WIDTH /
                                             2, 0))
                controlPoints.append(self.endItem.pos() + endPt -
                                     QPointF(ModelerGraphicItem.BOX_WIDTH /
                                             2, 0))
                controlPoints.append(self.endItem.pos() + endPt)
        else:
            controlPoints.append(self.startItem.pos())
            controlPoints.append(self.startItem.pos() +
                                 QPointF(ModelerGraphicItem.BOX_WIDTH / 2, 0))
            controlPoints.append(self.endItem.pos() + endPt -
                                 QPointF(ModelerGraphicItem.BOX_WIDTH / 2, 0))
            controlPoints.append(self.endItem.pos() + endPt)
            pt = QPointF(self.endItem.pos() + endPt + QPointF(-3, -3))
            painter.drawEllipse(pt.x(), pt.y(), 6, 6)

        path = QPainterPath()
        path.moveTo(controlPoints[0])
        path.cubicTo(*controlPoints[1:])
        painter.strokePath(path, painter.pen())
        self.setPath(path)
예제 #15
0
파일: test.py 프로젝트: jhennies/py_devel
    def paintEvent(self, QPaintEvent):

        back = (numpy.ones((100, 200, 300)) * 0).astype(numpy.uint8)
        back[0:60, 0:60, 0:60] = 255
        ol = (numpy.zeros((100, 200, 300))).astype(numpy.uint8)
        ol[0:99, 0:99, 0:99] = 120
        ol[0:99, 120:140, 0:99] = 255

        path = QPainterPath()
        path.addRect(20, 20, 60, 60)
        path.moveTo(0, 0)
        path.cubicTo(99, 0, 50, 50, 99, 99)
        path.cubicTo(0, 99, 50, 50, 0, 0)
        painter = QPainter(self)
        painter.fillRect(0, 0, 100, 100, Qt.Qt.red)
예제 #16
0
파일: test.py 프로젝트: jhennies/py_devel
    def paintEvent(self, QPaintEvent):

        back = (numpy.ones((100, 200, 300)) * 0).astype(numpy.uint8)
        back[0:60, 0:60, 0:60] = 255
        ol = (numpy.zeros((100, 200, 300))).astype(numpy.uint8)
        ol[0:99, 0:99, 0:99] = 120
        ol[0:99, 120:140, 0:99] = 255

        path = QPainterPath()
        path.addRect(20, 20, 60, 60)
        path.moveTo(0, 0)
        path.cubicTo(99, 0,  50, 50,  99, 99)
        path.cubicTo(0, 99,  50, 50,  0, 0)
        painter = QPainter(self)
        painter.fillRect(0, 0, 100, 100, Qt.Qt.red)
예제 #17
0
    def paint(self, painter, option, widget=None):
        myPen = self.pen()
        myPen.setColor(self.myColor)
        painter.setPen(myPen)
        painter.setBrush(self.myColor)

        controlPoints = []
        endPt = self.endItem.getLinkPointForParameter(self.endIndex)
        startPt = self.startItem.getLinkPointForOutput(self.startIndex)
        if isinstance(self.startItem.element, Algorithm):
            if self.startIndex != -1:
                controlPoints.append(self.startItem.pos() + startPt)
                controlPoints.append(self.startItem.pos() + startPt
                        + QPointF(ModelerGraphicItem.BOX_WIDTH / 2, 0))
                controlPoints.append(self.endItem.pos() + endPt
                        - QPointF(ModelerGraphicItem.BOX_WIDTH / 2, 0))
                controlPoints.append(self.endItem.pos() + endPt)
                pt = QPointF(self.startItem.pos() + startPt
                        + QPointF(-3, -3))
                painter.drawEllipse(pt.x(), pt.y(), 6, 6)
                pt = QPointF(self.endItem.pos() + endPt +
                        QPointF(-3, -3))
                painter.drawEllipse(pt.x(), pt.y(), 6, 6)
            else:
                # Case where there is a dependency on an algorithm not
                # on an output
                controlPoints.append(self.startItem.pos() + startPt)
                controlPoints.append(self.startItem.pos() + startPt
                        + QPointF(ModelerGraphicItem.BOX_WIDTH / 2, 0))
                controlPoints.append(self.endItem.pos() + endPt
                        - QPointF(ModelerGraphicItem.BOX_WIDTH / 2, 0))
                controlPoints.append(self.endItem.pos() + endPt)
        else:
            controlPoints.append(self.startItem.pos())
            controlPoints.append(self.startItem.pos()
                    + QPointF(ModelerGraphicItem.BOX_WIDTH / 2, 0))
            controlPoints.append(self.endItem.pos() + endPt
                    - QPointF(ModelerGraphicItem.BOX_WIDTH / 2, 0))
            controlPoints.append(self.endItem.pos() + endPt)
            pt = QPointF(self.endItem.pos() + endPt + QPointF(-3, -3))
            painter.drawEllipse(pt.x(), pt.y(), 6, 6)

        path = QPainterPath()
        path.moveTo(controlPoints[0])
        path.cubicTo(*controlPoints[1:])
        painter.strokePath(path, painter.pen())
        self.setPath(path)
예제 #18
0
파일: linkitem.py 프로젝트: joshz/orange3
    def __updateCurve(self):
        self.prepareGeometryChange()
        if self.sourceAnchor and self.sinkAnchor:
            source_pos = self.sourceAnchor.anchorScenePos()
            sink_pos = self.sinkAnchor.anchorScenePos()
            source_pos = self.curveItem.mapFromScene(source_pos)
            sink_pos = self.curveItem.mapFromScene(sink_pos)
            # TODO: get the orthogonal angle to the anchors path.
            path = QPainterPath()
            path.moveTo(source_pos)
            path.cubicTo(source_pos + QPointF(60, 0), sink_pos - QPointF(60, 0), sink_pos)

            self.curveItem.setPath(path)
            self.sourceIndicator.setPos(source_pos)
            self.sinkIndicator.setPos(sink_pos)
            self.__updateText()
        else:
            self.setHoverState(False)
            self.curveItem.setPath(QPainterPath())
예제 #19
0
파일: eedge.py 프로젝트: raiscui/edd
    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)
예제 #20
0
파일: eedge.py 프로젝트: feeling1982113/edd
    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)
예제 #21
0
 def updatePath(self):
     self.endPoints = []
     controlPoints = []
     endPt = self.endItem.getLinkPointForParameter(self.endIndex)
     startPt = self.startItem.getLinkPointForOutput(self.startIndex)
     if isinstance(self.startItem.element, Algorithm):
         if self.startIndex != -1:
             controlPoints.append(self.startItem.pos() + startPt)
             controlPoints.append(self.startItem.pos() + startPt
                                  + QPointF(ModelerGraphicItem.BOX_WIDTH / 3, 0))
             controlPoints.append(self.endItem.pos() + endPt
                                  - QPointF(ModelerGraphicItem.BOX_WIDTH / 3, 0))
             controlPoints.append(self.endItem.pos() + endPt)
             pt = QPointF(self.startItem.pos() + startPt
                          + QPointF(-3, -3))
             self.endPoints.append(pt)
             pt = QPointF(self.endItem.pos() + endPt +
                          QPointF(-3, -3))
             self.endPoints.append(pt)
         else:
             # Case where there is a dependency on an algorithm not
             # on an output
             controlPoints.append(self.startItem.pos() + startPt)
             controlPoints.append(self.startItem.pos() + startPt
                                  + QPointF(ModelerGraphicItem.BOX_WIDTH / 3, 0))
             controlPoints.append(self.endItem.pos() + endPt
                                  - QPointF(ModelerGraphicItem.BOX_WIDTH / 3, 0))
             controlPoints.append(self.endItem.pos() + endPt)
     else:
         controlPoints.append(self.startItem.pos())
         controlPoints.append(self.startItem.pos()
                              + QPointF(ModelerGraphicItem.BOX_WIDTH / 3, 0))
         controlPoints.append(self.endItem.pos() + endPt
                              - QPointF(ModelerGraphicItem.BOX_WIDTH / 3, 0))
         controlPoints.append(self.endItem.pos() + endPt)
         pt = QPointF(self.endItem.pos() + endPt + QPointF(-3, -3))
         self.endPoints.append(pt)
     path = QPainterPath()
     path.moveTo(controlPoints[0])
     path.cubicTo(*controlPoints[1:])
     self.setPath(path)
예제 #22
0
    def __updateCurve(self):
        self.prepareGeometryChange()
        if self.sourceAnchor and self.sinkAnchor:
            source_pos = self.sourceAnchor.anchorScenePos()
            sink_pos = self.sinkAnchor.anchorScenePos()
            source_pos = self.curveItem.mapFromScene(source_pos)
            sink_pos = self.curveItem.mapFromScene(sink_pos)
            # TODO: get the orthogonal angle to the anchors path.
            path = QPainterPath()
            path.moveTo(source_pos)
            path.cubicTo(source_pos + QPointF(60, 0),
                         sink_pos - QPointF(60, 0),
                         sink_pos)

            self.curveItem.setPath(path)
            self.sourceIndicator.setPos(source_pos)
            self.sinkIndicator.setPos(sink_pos)
            self.__updateText()
        else:
            self.setHoverState(False)
            self.curveItem.setPath(QPainterPath())
예제 #23
0
def polygonToCurvedPath(polygon, radius):

    path = QPainterPath()
    for i, pt in enumerate(polygon):

        # TODO: if two points are too close to draw the desired radius, either remove those points or draw at smaller radius
        px, py = polygon[i - 1] if i > 0 else polygon[-1]
        nx, ny = polygon[i + 1] if i < len(polygon) - 1 else polygon[0]
        x, y = pt

        if px == x:
            dy = y - py
            r = radius if dy < 0 else -radius
            p1 = QPointF(x, y + r)
        else:
            dx = x - px
            r = radius if dx < 0 else -radius
            p1 = QPointF(x + r, y)

        if x == nx:
            dy = y - ny
            r = radius if dy < 0 else -radius
            p2 = QPointF(x, y + r)
        else:
            dx = x - nx
            r = radius if dx < 0 else -radius
            p2 = QPointF(x + r, y)

        if i == 0:
            path.moveTo(p1)
        else:
            path.lineTo(p1)
        path.cubicTo(pt, pt, p2)

    path.closeSubpath()
    return path
예제 #24
0
def polygonToCurvedPath(polygon, radius):
    
    path = QPainterPath()
    for i, pt in enumerate(polygon):
        
        # TODO: if two points are too close to draw the desired radius, either remove those points or draw at smaller radius
        px, py = polygon[i-1] if i > 0 else polygon[-1]
        nx, ny = polygon[i+1] if i < len(polygon) - 1 else polygon[0]
        x, y = pt
        
        if px == x:
            dy = y - py
            r = radius if dy < 0 else -radius
            p1 = QPointF(x, y + r)
        else:
            dx = x - px
            r = radius if dx < 0 else -radius
            p1 = QPointF(x + r, y)
        
        if x == nx:
            dy = y - ny
            r = radius if dy < 0 else -radius
            p2 = QPointF(x, y + r)
        else:
            dx = x - nx
            r = radius if dx < 0 else -radius
            p2 = QPointF(x + r, y)
        
        if i == 0:
            path.moveTo(p1)
        else:
            path.lineTo(p1)
        path.cubicTo(pt, pt, p2)

    path.closeSubpath()
    return path
예제 #25
0
파일: eedge.py 프로젝트: raiscui/edd
    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)
예제 #26
0
    def paintEvent(self, event):
        option = QStyleOption()
        option.initFrom(self)

        contents_rect = self.style().subElementRect(QStyle.SE_FrameContents, option, self) or self.contentsRect() # the SE_FrameContents rect is Null unless the stylesheet defines decorations

        if self.graphStyle == self.BarStyle:
            graph_width = self.__dict__['graph_width'] = int(ceil(float(contents_rect.width()) / self.horizontalPixelsPerUnit))
        else:
            graph_width = self.__dict__['graph_width'] = int(ceil(float(contents_rect.width() - 1) / self.horizontalPixelsPerUnit) + 1)

        max_value = self.__dict__['max_value'] = max(chain([0], *(islice(reversed(graph.data), graph_width) for graph in self.graphs if graph.enabled)))

        if self.graphHeight == self.AutomaticHeight or self.graphHeight < 0:
            graph_height = self.__dict__['graph_height'] = max(self.scaler.get_height(max_value), self.minHeight)
        else:
            graph_height = self.__dict__['graph_height'] = max(self.graphHeight, self.minHeight)

        if self.graphStyle == self.BarStyle:
            height_scaling = float(contents_rect.height()) / graph_height
        else:
            height_scaling = float(contents_rect.height() - self.lineThickness) / graph_height

        painter = QStylePainter(self)
        painter.drawPrimitive(QStyle.PE_Widget, option)

        painter.setClipRect(contents_rect)

        painter.save()
        painter.translate(contents_rect.x() + contents_rect.width() - 1, contents_rect.y() + contents_rect.height() - 1)
        painter.scale(-1, -1)

        painter.setRenderHint(QStylePainter.Antialiasing, self.graphStyle != self.BarStyle)

        for graph in (graph for graph in self.graphs if graph.enabled and graph.data):
            if self.boundary is not None and 0 < self.boundary < graph_height:
                boundary_width = min(5.0/height_scaling, self.boundary-0, graph_height-self.boundary)
                pen_color = QLinearGradient(0, (self.boundary - boundary_width) * height_scaling, 0, (self.boundary + boundary_width) * height_scaling)
                pen_color.setColorAt(0, graph.color)
                pen_color.setColorAt(1, graph.over_boundary_color)
                brush_color = QLinearGradient(0, (self.boundary - boundary_width) * height_scaling, 0, (self.boundary + boundary_width) * height_scaling)
                brush_color.setColorAt(0, self.color_with_alpha(graph.color, self.fillTransparency))
                brush_color.setColorAt(1, self.color_with_alpha(graph.over_boundary_color, self.fillTransparency))
            else:
                pen_color = graph.color
                brush_color = self.color_with_alpha(graph.color, self.fillTransparency)
            dataset = islice(reversed(graph.data), graph_width)
            if self.graphStyle == self.BarStyle:
                lines = [QLine(x*self.horizontalPixelsPerUnit, 0, x*self.horizontalPixelsPerUnit, y*height_scaling) for x, y in enumerate(dataset)]
                painter.setPen(QPen(pen_color, self.lineThickness))
                painter.drawLines(lines)
            else:
                painter.translate(0, +self.lineThickness/2 - 1)

                if self.smoothEnvelope and self.smoothFactor > 0:
                    min_value = 0
                    max_value = graph_height * height_scaling
                    cx_offset = self.horizontalPixelsPerUnit / 3.0
                    smoothness = self.smoothFactor

                    last_values = deque(3*[dataset.next() * height_scaling], maxlen=3) # last 3 values: 0 last, 1 previous, 2 previous previous

                    envelope = QPainterPath()
                    envelope.moveTo(0, last_values[0])
                    for x, y in enumerate(dataset, 1):
                        x = x * self.horizontalPixelsPerUnit
                        y = y * height_scaling * (1 - smoothness) + last_values[0] * smoothness
                        last_values.appendleft(y)
                        c1x = x - cx_offset * 2
                        c2x = x - cx_offset
                        c1y = limit((1 + smoothness) * last_values[1] - smoothness * last_values[2], min_value, max_value) # same gradient as previous previous value to previous value
                        c2y = limit((1 - smoothness) * last_values[0] + smoothness * last_values[1], min_value, max_value) # same gradient as previous value to last value
                        envelope.cubicTo(c1x, c1y, c2x, c2y, x, y)
                else:
                    envelope = QPainterPath()
                    envelope.addPolygon(QPolygonF([QPointF(x*self.horizontalPixelsPerUnit, y*height_scaling) for x, y in enumerate(dataset)]))

                if self.fillEnvelope or graph.fill_envelope:
                    first_element = envelope.elementAt(0)
                    last_element = envelope.elementAt(envelope.elementCount() - 1)
                    fill_path = QPainterPath()
                    fill_path.moveTo(last_element.x, last_element.y)
                    fill_path.lineTo(last_element.x + 1, last_element.y)
                    fill_path.lineTo(last_element.x + 1, -self.lineThickness)
                    fill_path.lineTo(-self.lineThickness, -self.lineThickness)
                    fill_path.lineTo(-self.lineThickness, first_element.y)
                    fill_path.connectPath(envelope)
                    painter.fillPath(fill_path, brush_color)

                painter.strokePath(envelope, QPen(pen_color, self.lineThickness, join=Qt.RoundJoin))

                painter.translate(0, -self.lineThickness/2 + 1)

        if self.boundary is not None and self.boundaryColor:
            painter.setRenderHint(QStylePainter.Antialiasing, False)
            painter.setPen(QPen(self.boundaryColor, 1.0))
            painter.drawLine(0, self.boundary*height_scaling, contents_rect.width(), self.boundary*height_scaling)

        painter.restore()

        # queue the 'updated' signal to be emited after returning to the main loop
        QMetaObject.invokeMethod(self, 'updated', Qt.QueuedConnection)
예제 #27
0
    def paint(self, painter, rect, widget_size, draw_highlight):
        GraphXYView.paint(self, painter, rect, widget_size, draw_highlight)
        smooth = 2.5 # this is invert smoothing, increase it to sharpen graph

        if not self.model():
            return

        option = self.viewOptions()

        background = option.palette.base()
        foreground = QPen(option.palette.color(QPalette.Foreground))

        # Handle step by step size increment
        step_width = floor(widget_size.width() / RESIZE_INCREMENT) * RESIZE_INCREMENT
        step_height = floor(widget_size.height() / RESIZE_INCREMENT) * RESIZE_INCREMENT

        if self.model().rowCount(self.rootIndex()) != 0:
            value_max = self.getValueMaxAll()
        else:
            value_max = 0

        # If there is no data yet, or the max is at 0, use a max of 10 to dispaly an axe
        if self.fetcher.fragment.type == 'LoadStream':
            if value_max < 100:
                value_max = 100
        else:
            if value_max == 0:
                value_max = 10

        if len(self.data) != 0:
            xmin = self.getValueMin(0)
            xmax = self.getValueMax(0)
        else:
            return

        if xmin == xmax:
            return # avoid division by 0

        painter.save()

        # Offset to cerrectly center the graph after the resizing due to the step by step increment
        painter.translate((widget_size.width() - step_width) / 2.0, (widget_size.height() - step_height) / 2.0)

        painter.setPen(foreground)

        # Draw lines
        fm = QFontMetrics(painter.font())
        margin_size = fm.width("0")

        if self.fetcher.fragment.type == 'TrafficStream':
            x_axe_off = fm.width(unicode(value_max * 2000))
        else:
            x_axe_off = fm.width(unicode(value_max * 200))

        # Order them by max mean value
        means = {}
        for col in xrange(1, len(self.data[0])):
            means[col] = self.getMeanValue(col)

        def mean_sorter(x, y):
            return cmp(y[1], x[1])

        means_sorted = means.items()
        means_sorted.sort(mean_sorter)

        def slope_by_index(points, index, sens):
            if index >= len(points):
                return 0
            if index == 0:
                return points[index].y() + (points[index+1].y()-points[index].y())/smooth
            if index == (len(points) - 1):
                return points[index].y() - (points[index].y()-points[index-1].y())/smooth
            vpoints = [ points[index-1].y(), points[index].y(), points[index+1].y()]
            if points[index].y() == max(vpoints):
                return points[index].y()
            if points[index].y() == min(vpoints):
                return points[index].y()
            if sens == 0:
                return points[index].y() + (points[index+1].y()-points[index].y())/smooth
                #return points[index].y() + (points[index+1].y() - points[index-1].y()) / (points[index+1].x()-points[index-1].x()) * (points[index+1].x() - points[index].x()) / smooth
            else:
                return points[index].y() - (points[index].y()-points[index-1].y())/smooth
                #return points[index].y() + (points[index+1].y() - points[index-1].y()) / (points[index+1].x()-points[index-1].x()) * (points[index-1].x() - points[index].x()) / smooth

        colors = odict()

        for _col in means_sorted:
            col = _col[0]
            path = QPainterPath()
            path.setFillRule(Qt.WindingFill)
            last_point = None
            height_max = 0.0
            width_max =  step_width - 2 * margin_size - x_axe_off
            height_max = (step_height * (1.0 - TITLE_AREA)) - 2 * margin_size

            points = []

            for row in xrange(len(self.data)):
                index = self.model().index(row, col, self.rootIndex())
                value = index.data().toInt()[0]
                x_value = int(self.data[row][0])
                #print "x=", x_value, "y=", value

                if value >= 0.0:
                    height = height_max * value/value_max

                    x = (float(x_value - xmin) / float(xmax - xmin)) * width_max
                    point = QPointF(x + margin_size + x_axe_off, height_max - height + margin_size)

                    points.append(point)

            for index, point in enumerate(points):
                # draw simple point
                painter.setBrush(QBrush(QColor(self.colours[col]).dark(200)))
                painter.drawEllipse(QRectF(point.x() - 2, point.y() - 2, 4, 4))
            # init drawing
                if index == 0:
                    path.moveTo(point)
                    continue

                px = points[index-1].x() + (points[index].x() - points[index-1].x()) / smooth
                py = slope_by_index(points, index-1, 0)
                c1 = QPointF(px, py)
                px = points[index].x() - ( points[index].x() - points[index-1].x() ) / smooth
                py = slope_by_index(points, index, 1)
                c2 = QPointF(px, py)

                path.cubicTo(c1, c2, point)

            last_point = points[len(points)-1]
            if last_point:
                txt = self.model().headerData(col, Qt.Horizontal).toString()
                txt_width = fm.width(txt)
                txt_height = fm.height()

                colors[txt] = QColor(self.colours[col])
                path.lineTo(QPointF(x + margin_size + x_axe_off, height_max + margin_size))
                path.lineTo(QPointF(margin_size + x_axe_off, height_max + margin_size))

            color = QColor(self.colours[col])
            color.setAlpha(200)

            ## Create the gradient effect
            grad = QLinearGradient(QPointF(0.0, 0.0), QPointF(0.0, height_max))
            grad.setColorAt(1.0, color.dark(150))
            grad.setColorAt(0.95, color)
            grad.setColorAt(0.05, color)
            grad.setColorAt(0.0, Qt.white)

            painter.setBrush(QBrush(grad))

            painter.drawPath(path)

        # Graduations
        nbr_grad = xmax - xmin
        dgrad = 1
        while nbr_grad > 10:
            nbr_grad = floor(nbr_grad / 10)
            dgrad = dgrad * 10

        if nbr_grad <= 2:
            dgrad = dgrad / 10
            nbr_grad = 10

        # Prevent for infinite loops.
        if dgrad < 1:
            dgrad = 1

        dx = (float(dgrad) / float(xmax-xmin)) * width_max
        text_dy = fm.height()

        i = 0
        while (i * dgrad) <= xmax - xmin:

            if self.fetcher.fragment.type != 'TrafficStream' or (self.fetcher.fragment.type == 'TrafficStream' and i % 4 == 0):
                grad_width = fm.width("0")
                painter.drawLine(margin_size + x_axe_off + (i*dx), height_max + margin_size, margin_size + x_axe_off + (i*dx), height_max + margin_size + grad_width)
                text = unicode(int(dgrad * i))

                # Legend drawing:
                painter.translate(margin_size + x_axe_off + (i*dx), height_max + margin_size + 2*grad_width)
                painter.rotate(-45.0)
                int_time = (i * dgrad) + xmin
                text = QString('%ds' % (xmax - int_time))

                txt_width = fm.width(text)
                painter.drawText(QRect(-txt_width, -dx, txt_width, 2*dx), Qt.AlignRight|Qt.AlignVCenter, text)
                painter.rotate(45.0)
                painter.translate(-(margin_size + x_axe_off + (i*dx)), -(height_max + margin_size + 2*grad_width))

            i = i + 1

        interval = 0
        height = height_max + margin_size + txt_width * sin(45) + 30
        for k, v in colors.iteritems():
            painter.setPen(v)
            legendRect = QRect(interval, height, 10, 10)
            painter.drawRect(legendRect)
            painter.fillRect(legendRect, QBrush(v))
            painter.setPen(foreground)
            txt_width = fm.width(k)
            txt_height = fm.height()
            painter.drawText(QRect(interval + 10, height, txt_width, txt_height), Qt.AlignRight|Qt.AlignVCenter, k)
            interval += 20 + txt_width

        painter.translate((step_width - widget_size.width()) / 2.0, (step_height - widget_size.height()) / 2.0)
        painter.restore()
예제 #28
0
# from lazyflow.operators import OpCompressedCache

from PyQt4 import QtCore, uic
from PyQt4.QtGui import QApplication, QPainter, QPainterPath
from PyQt4 import QtGui
from PyQt4 import Qt

app = QtGui.QApplication([])

scene = QtGui.QGraphicsScene()
scene.addText("Hello World!")

back = (numpy.ones((100, 200, 300)) * 0).astype(numpy.uint8)
back[0:60, 0:60, 0:60] = 255
ol = (numpy.zeros((100, 200, 300))).astype(numpy.uint8)
ol[0:99, 0:99, 0:99] = 120
ol[0:99, 120:140, 0:99] = 255

path = QPainterPath()
path.addRect(20, 20, 60, 60)
path.moveTo(0, 0)
path.cubicTo(99, 0,  50, 50,  99, 99)
path.cubicTo(0, 99,  50, 50,  0, 0)

scene.addPath(path)

view = QtGui.QGraphicsView(scene)
view.show()

app.exec_()
예제 #29
0
    def render(o):
        path = QPainterPath()

        # unit_x gives offset and direction of the x base vector. Start and end should be the grid points.

        # move the endpoints inwards an unnoticable bit, so that the intersection detector
        # won't trip on the common endpoint.
        u_x = QLineF(o.unit_x.pointAt(0.0001), o.unit_x.pointAt(0.9999))

        path.moveTo(u_x.p1())

        if o.is_straight:
            path.lineTo(u_x.p2())
            return path

        if o.flipped:
            u_x = QLineF(u_x.p2(), u_x.p1())

        u_y = u_x.normalVector()
        # move y unit to start at (0,0).
        u_y.translate(-u_y.p1())

        scaling = o.length_base / u_x.length() * o.size_correction
        if o.basewidth * scaling > 0.8:
            # Plug is too large for the edge length. Make it smaller.
            scaling = 0.8 / o.basewidth

        # some magic numbers here... carefully fine-tuned, better leave them as they are.
        ends_ctldist = 0.4
        #base_lcdist = 0.1 * scaling
        base_ucdist = 0.05 * scaling
        knob_lcdist = 0.6 * o.knobsize * scaling
        knob_ucdist = 0.8 * o.knobsize * scaling

        # set up piece -- here is where the really interesting stuff happens.
        # We will work from the ends inwards, so that symmetry counterparts are adjacent.
        # The QLine.pointAt function is used to transform everything into the coordinate
        # space defined by the us.
        # -- end points

        r1y = ends_ctldist * o.basepos * dsin(o.startangle)
        q6y = ends_ctldist * (1. - o.basepos) * dsin(o.endangle)
        p1 = u_x.p1()
        p6 = u_x.p2()
        r1 = u_x.pointAt(
            ends_ctldist * o.basepos * dcos(o.startangle)) + u_y.pointAt(r1y)
        q6 = u_x.pointAt(1. - ends_ctldist * (1. - o.basepos) *
                         dcos(o.endangle)) + u_y.pointAt(q6y)

        # -- base points
        p2x = o.basepos - 0.5 * o.basewidth * scaling
        p5x = o.basepos + 0.5 * o.basewidth * scaling

        if p2x < 0.1 or p5x > 0.9:
            # knob to large. center knob on the edge. (o.basewidth * scaling < 0.8 -- see above)
            p2x = 0.5 - 0.5 * o.basewidth * scaling
            p5x = 0.5 + 0.5 * o.basewidth * scaling

        #base_y = r1y > q6y ? r1y : q6y
        #base_y = 0.5*(r1y + q6y)
        base_y = -o.baseroundness * ends_ctldist * min(p2x, 1. - p5x)
        if base_y > 0:
            base_y = 0

        base_lcy = base_y * 2.0

        base_y += base_ucdist / 2
        base_lcy -= base_ucdist / 2
        #base_lcy = r1y
        #if (q6y < r1y): base_lcy = q6y

        # at least -base_ucdist from base_y
        #if (base_lcy > base_y - base_ucdist): base_lcy = base_y-base_ucdist

        q2 = u_x.pointAt(p2x) + u_y.pointAt(base_lcy)
        r5 = u_x.pointAt(p5x) + u_y.pointAt(base_lcy)
        p2 = u_x.pointAt(p2x) + u_y.pointAt(base_y)
        p5 = u_x.pointAt(p5x) + u_y.pointAt(base_y)
        r2 = u_x.pointAt(p2x) + u_y.pointAt(base_y + base_ucdist)
        q5 = u_x.pointAt(p5x) + u_y.pointAt(base_y + base_ucdist)

        if o._is_plugless:
            if not o.flipped:
                path.cubicTo(r1, q2, p2)
                path.cubicTo(r2, q5, p5)
                path.cubicTo(r5, q6, p6)
            else:
                path.cubicTo(q6, r5, p5)
                path.cubicTo(q5, r2, p2)
                path.cubicTo(q2, r1, p1)
            return path

        # -- knob points
        p3x = p2x - o.knobsize * scaling * dsin(o.knobangle - o.knobtilt)
        p4x = p5x + o.knobsize * scaling * dsin(o.knobangle + o.knobtilt)
        # for the y coordinate, knobtilt sign was swapped. Knobs look better this way...
        # like x offset from base points y, but that is 0.
        p3y = o.knobsize * scaling * dcos(o.knobangle + o.knobtilt) + base_y
        p4y = o.knobsize * scaling * dcos(o.knobangle - o.knobtilt) + base_y

        q3 = u_x.pointAt(p3x) + u_y.pointAt(p3y - knob_lcdist)
        r4 = u_x.pointAt(p4x) + u_y.pointAt(p4y - knob_lcdist)
        p3 = u_x.pointAt(p3x) + u_y.pointAt(p3y)
        p4 = u_x.pointAt(p4x) + u_y.pointAt(p4y)
        r3 = u_x.pointAt(p3x) + u_y.pointAt(p3y + knob_ucdist)
        q4 = u_x.pointAt(p4x) + u_y.pointAt(p4y + knob_ucdist)

        # done setting up. construct path.
        # if flipped, add points in reverse.
        if not o.flipped:
            path.cubicTo(r1, q2, p2)
            path.cubicTo(r2, q3, p3)
            path.cubicTo(r3, q4, p4)
            path.cubicTo(r4, q5, p5)
            path.cubicTo(r5, q6, p6)
        else:
            path.cubicTo(q6, r5, p5)
            path.cubicTo(q5, r4, p4)
            path.cubicTo(q4, r3, p3)
            path.cubicTo(q3, r2, p2)
            path.cubicTo(q2, r1, p1)
        return path
예제 #30
0
파일: graph.py 프로젝트: kogmbh/blink-qt
    def paintEvent(self, event):
        option = QStyleOption()
        option.initFrom(self)

        contents_rect = self.style().subElementRect(QStyle.SE_FrameContents, option, self) or self.contentsRect() # the SE_FrameContents rect is Null unless the stylesheet defines decorations

        if self.graphStyle == self.BarStyle:
            graph_width = self.__dict__['graph_width'] = int(ceil(float(contents_rect.width()) / self.horizontalPixelsPerUnit))
        else:
            graph_width = self.__dict__['graph_width'] = int(ceil(float(contents_rect.width() - 1) / self.horizontalPixelsPerUnit) + 1)

        max_value = self.__dict__['max_value'] = max(chain([0], *(islice(reversed(graph.data), graph_width) for graph in self.graphs if graph.enabled)))

        if self.graphHeight == self.AutomaticHeight or self.graphHeight < 0:
            graph_height = self.__dict__['graph_height'] = max(self.scaler.get_height(max_value), self.minHeight)
        else:
            graph_height = self.__dict__['graph_height'] = max(self.graphHeight, self.minHeight)

        if self.graphStyle == self.BarStyle:
            height_scaling = float(contents_rect.height()) / graph_height
        else:
            height_scaling = float(contents_rect.height() - self.lineThickness) / graph_height

        painter = QStylePainter(self)
        painter.drawPrimitive(QStyle.PE_Widget, option)

        painter.setClipRect(contents_rect)

        painter.save()
        painter.translate(contents_rect.x() + contents_rect.width() - 1, contents_rect.y() + contents_rect.height() - 1)
        painter.scale(-1, -1)

        painter.setRenderHint(QStylePainter.Antialiasing, self.graphStyle != self.BarStyle)

        for graph in (graph for graph in self.graphs if graph.enabled and graph.data):
            if self.boundary is not None and 0 < self.boundary < graph_height:
                boundary_width = min(5.0/height_scaling, self.boundary-0, graph_height-self.boundary)
                pen_color = QLinearGradient(0, (self.boundary - boundary_width) * height_scaling, 0, (self.boundary + boundary_width) * height_scaling)
                pen_color.setColorAt(0, graph.color)
                pen_color.setColorAt(1, graph.over_boundary_color)
                brush_color = QLinearGradient(0, (self.boundary - boundary_width) * height_scaling, 0, (self.boundary + boundary_width) * height_scaling)
                brush_color.setColorAt(0, self.color_with_alpha(graph.color, self.fillTransparency))
                brush_color.setColorAt(1, self.color_with_alpha(graph.over_boundary_color, self.fillTransparency))
            else:
                pen_color = graph.color
                brush_color = self.color_with_alpha(graph.color, self.fillTransparency)
            dataset = islice(reversed(graph.data), graph_width)
            if self.graphStyle == self.BarStyle:
                lines = [QLine(x*self.horizontalPixelsPerUnit, 0, x*self.horizontalPixelsPerUnit, y*height_scaling) for x, y in enumerate(dataset)]
                painter.setPen(QPen(pen_color, self.lineThickness))
                painter.drawLines(lines)
            else:
                painter.translate(0, +self.lineThickness/2 - 1)

                if self.smoothEnvelope and self.smoothFactor > 0:
                    min_value = 0
                    max_value = graph_height * height_scaling
                    cx_offset = self.horizontalPixelsPerUnit / 3.0
                    smoothness = self.smoothFactor

                    last_values = deque(3*[dataset.next() * height_scaling], maxlen=3) # last 3 values: 0 last, 1 previous, 2 previous previous

                    envelope = QPainterPath()
                    envelope.moveTo(0, last_values[0])
                    for x, y in enumerate(dataset, 1):
                        x = x * self.horizontalPixelsPerUnit
                        y = y * height_scaling * (1 - smoothness) + last_values[0] * smoothness
                        last_values.appendleft(y)
                        c1x = x - cx_offset * 2
                        c2x = x - cx_offset
                        c1y = limit((1 + smoothness) * last_values[1] - smoothness * last_values[2], min_value, max_value) # same gradient as previous previous value to previous value
                        c2y = limit((1 - smoothness) * last_values[0] + smoothness * last_values[1], min_value, max_value) # same gradient as previous value to last value
                        envelope.cubicTo(c1x, c1y, c2x, c2y, x, y)
                else:
                    envelope = QPainterPath()
                    envelope.addPolygon(QPolygonF([QPointF(x*self.horizontalPixelsPerUnit, y*height_scaling) for x, y in enumerate(dataset)]))

                if self.fillEnvelope or graph.fill_envelope:
                    first_element = envelope.elementAt(0)
                    last_element = envelope.elementAt(envelope.elementCount() - 1)
                    fill_path = QPainterPath()
                    fill_path.moveTo(last_element.x, last_element.y)
                    fill_path.lineTo(last_element.x + 1, last_element.y)
                    fill_path.lineTo(last_element.x + 1, -self.lineThickness)
                    fill_path.lineTo(-self.lineThickness, -self.lineThickness)
                    fill_path.lineTo(-self.lineThickness, first_element.y)
                    fill_path.connectPath(envelope)
                    painter.fillPath(fill_path, brush_color)

                painter.strokePath(envelope, QPen(pen_color, self.lineThickness, join=Qt.RoundJoin))

                painter.translate(0, -self.lineThickness/2 + 1)

        if self.boundary is not None and self.boundaryColor:
            painter.setRenderHint(QStylePainter.Antialiasing, False)
            painter.setPen(QPen(self.boundaryColor, 1.0))
            painter.drawLine(0, self.boundary*height_scaling, contents_rect.width(), self.boundary*height_scaling)

        painter.restore()

        # queue the 'updated' signal to be emited after returning to the main loop
        QMetaObject.invokeMethod(self, 'updated', Qt.QueuedConnection)