Exemple #1
0
    def _drawPlotLine(self, painter, xvals, yvals, posn, xdata, ydata,
                      cliprect):
        """Draw the line connecting the points."""

        pts = self._getLinePoints(xvals, yvals, posn, xdata, ydata)
        if len(pts) < 2:
            return
        s = self.settings

        if not s.FillBelow.hide:
            # construct polygon to draw filled region
            polypts = qt4.QPolygonF([qt4.QPointF(pts[0].x(), posn[3])])
            polypts += pts
            polypts.append(qt4.QPointF(pts[len(pts) - 1].x(), posn[3]))

            utils.brushExtFillPolygon(painter, s.FillBelow, cliprect, polypts)

        if not s.FillAbove.hide:
            polypts = qt4.QPolygonF([qt4.QPointF(pts[0].x(), posn[1])])
            polypts += pts
            polypts.append(qt4.QPointF(pts[len(pts) - 1].x(), posn[1]))

            utils.brushExtFillPolygon(painter, s.FillAbove, cliprect, polypts)

        # draw line between points
        if not s.PlotLine.hide:
            painter.setPen(s.PlotLine.makeQPen(painter))
            utils.plotClippedPolyline(painter, cliprect, pts)
Exemple #2
0
 def setClip(self, painter, bounds):
     '''Set clipping for graph.'''
     p = qt4.QPainterPath()
     p.addEllipse(
         qt4.QRectF(qt4.QPointF(bounds[0], bounds[1]),
                    qt4.QPointF(bounds[2], bounds[3])))
     painter.setClipPath(p)
Exemple #3
0
    def drawKeySymbol(self, number, painter, x, y, width, height):
        """Draw the plot symbol and/or line."""
        painter.save()
        cliprect = qt4.QRectF(qt4.QPointF(x, y),
                              qt4.QPointF(x + width, y + height))
        painter.setClipRect(cliprect)

        # draw sample error bar
        s = self.settings
        size = s.get('markerSize').convert(painter)
        style = s.errorStyle

        # make some fake error bar data to plot
        xv = s.get('xData').getData(self.document)
        yv = s.get('yData').getData(self.document)
        yp = y + height / 2
        xpts = N.array([x - width, x + width / 2, x + 2 * width])
        ypts = N.array([yp, yp, yp])

        # size of error bars in key
        errorsize = height * 0.4

        # make points for error bars (if any)
        if xv and xv.hasErrors():
            xneg = N.array(
                [x - width, x + width / 2 - errorsize, x + 2 * width])
            xpos = N.array(
                [x - width, x + width / 2 + errorsize, x + 2 * width])
        else:
            xneg = xpos = xpts
        if yv and yv.hasErrors():
            yneg = N.array([yp - errorsize, yp - errorsize, yp - errorsize])
            ypos = N.array([yp + errorsize, yp + errorsize, yp + errorsize])
        else:
            yneg = ypos = ypts

        # plot error bar
        painter.setPen(s.ErrorBarLine.makeQPenWHide(painter))
        for function in _errorBarFunctionMap[style]:
            function(style, xneg, xpos, yneg, ypos, xpts, ypts, s, painter,
                     cliprect)

        # draw line
        if not s.PlotLine.hide:
            painter.setPen(s.PlotLine.makeQPen(painter))
            painter.drawLine(qt4.QPointF(x, yp), qt4.QPointF(x + width, yp))

        # draw marker
        if not s.MarkerLine.hide or not s.MarkerFill.hide:
            if not s.MarkerFill.hide:
                painter.setBrush(s.MarkerFill.makeQBrush())

            if not s.MarkerLine.hide:
                painter.setPen(s.MarkerLine.makeQPen(painter))
            else:
                painter.setPen(qt4.QPen(qt4.Qt.NoPen))

            utils.plotMarker(painter, x + width / 2, yp, s.marker, size)

        painter.restore()
Exemple #4
0
    def _plotLine(self, painter, xpts, ypts, bounds, clip):
        """ Plot the points in xpts, ypts."""
        x1, y1, x2, y2 = bounds

        maxdeltax = (x2 - x1) * 3 / 4
        maxdeltay = (y2 - y1) * 3 / 4

        # idea is to collect points until we go out of the bounds
        # or reach the end, then plot them
        pts = qt4.QPolygonF()
        lastx = lasty = -65536
        for x, y in itertools.izip(xpts, ypts):

            # ignore point if it outside sensible bounds
            if x < -32767 or y < -32767 or x > 32767 or y > 32767:
                if len(pts) >= 2:
                    utils.plotClippedPolyline(painter, clip, pts)
                    pts.clear()
            else:
                # if the jump wasn't too large, add the point to the points
                if abs(x - lastx) < maxdeltax and abs(y - lasty) < maxdeltay:
                    pts.append(qt4.QPointF(x, y))
                else:
                    # draw what we have until now, and start a new line
                    if len(pts) >= 2:
                        utils.plotClippedPolyline(painter, clip, pts)
                    pts.clear()
                    pts.append(qt4.QPointF(x, y))

            lastx = x
            lasty = y

        # draw remaining points
        if len(pts) >= 2:
            utils.plotClippedPolyline(painter, clip, pts)
Exemple #5
0
    def draw(self, parentposn, painthelper, outerbounds=None):
        '''Update the margins before drawing.'''

        s = self.settings

        margins = (s.get('leftMargin').convert(painthelper),
                   s.get('topMargin').convert(painthelper),
                   s.get('rightMargin').convert(painthelper),
                   s.get('bottomMargin').convert(painthelper))

        bounds = self.computeBounds(parentposn, painthelper, margins=margins)
        maxbounds = self.computeBounds(parentposn, painthelper)

        # controls for adjusting graph margins
        painter = painthelper.painter(self, bounds)
        painthelper.setControlGraph(self, [
            controlgraph.ControlMarginBox(self, bounds, maxbounds, painthelper)
        ])

        # do no painting if hidden
        if s.hide:
            return bounds

        # set graph rectangle attributes
        path = qt4.QPainterPath()
        path.addRect(
            qt4.QRectF(qt4.QPointF(bounds[0], bounds[1]),
                       qt4.QPointF(bounds[2], bounds[3])))
        utils.brushExtFillPath(painter,
                               s.Background,
                               path,
                               stroke=s.Border.makeQPenWHide(painter))

        # do normal drawing of children
        # iterate over children in reverse order
        for c in reversed(self.children):
            c.draw(bounds, painthelper, outerbounds=outerbounds)

        # now need to find axes which aren't children, and draw those again
        axestodraw = set()
        childrennames = set()
        for c in self.children:
            childrennames.add(c.name)
            try:
                for axis in c.getAxesNames():
                    axestodraw.add(axis)
            except AttributeError:
                pass

        axestodraw = axestodraw - childrennames
        if axestodraw:
            # now redraw all these axes if they aren't children of us
            axeswidgets = self.getAxes(axestodraw)
            for w in axeswidgets:
                if w is not None:
                    w.draw(bounds, painthelper, outerbounds=outerbounds)

        return bounds
Exemple #6
0
 def renderPage(self, size, dpi, painter):
     """Render page using paint helper to painter.
     This first renders to the helper, then to the painter
     """
     helper = painthelper.PaintHelper(size, dpi=dpi, directpaint=painter)
     painter.setClipRect(qt4.QRectF(qt4.QPointF(0, 0), qt4.QPointF(*size)))
     self.doc.paintTo(helper, self.pagenumber)
     painter.restore()
     painter.end()
Exemple #7
0
    def drawKeySymbol(self, number, painter, x, y, width, height):
        """Draw the plot symbol and/or line."""

        s = self.settings
        yp = y + height / 2

        # draw line
        if not s.Line.hide:
            painter.setBrush(qt4.QBrush())
            painter.setPen(s.Line.makeQPen(painter))
            painter.drawLine(qt4.QPointF(x, yp), qt4.QPointF(x + width, yp))
Exemple #8
0
    def draw(self, posn, phelper, outerbounds=None):
        """Draw the text label."""

        s = self.settings
        d = self.document

        # exit if hidden
        if s.hide or s.Text.hide:
            return

        text = s.get('label').getData(d)

        xp, yp = self._getPlotterCoords(posn)
        if xp is None or yp is None:
            # we can't calculate coordinates
            return

        clip = None
        if s.clip:
            clip = qt4.QRectF(qt4.QPointF(posn[0], posn[1]),
                              qt4.QPointF(posn[2], posn[3]))
        painter = phelper.painter(self, posn, clip=clip)
        textpen = s.get('Text').makeQPen()
        painter.setPen(textpen)
        font = s.get('Text').makeQFont(painter)

        # we should only be able to move non-dataset labels
        isnotdataset = (not s.get('xPos').isDataset(d)
                        and not s.get('yPos').isDataset(d))

        controlgraphitems = []
        for index, (x, y, t) in enumerate(
                itertools.izip(xp, yp, itertools.cycle(text))):
            # render the text
            tbounds = utils.Renderer(painter, font, x, y, t,
                                     TextLabel.cnvtalignhorz[s.alignHorz],
                                     TextLabel.cnvtalignvert[s.alignVert],
                                     s.angle).render()

            # add cgi for adjustable positions
            if isnotdataset:
                cgi = controlgraph.ControlMovableBox(self,
                                                     tbounds,
                                                     phelper,
                                                     crosspos=(x, y))
                cgi.labelpt = (x, y)
                cgi.widgetposn = posn
                cgi.index = index
                controlgraphitems.append(cgi)

        phelper.setControlGraph(self, controlgraphitems)
Exemple #9
0
    def drawGraph(self, painter, bounds, datarange, outerbounds=None):
        '''Plot graph area and axes.'''

        s = self.settings

        xw, yw = bounds[2]-bounds[0], bounds[3]-bounds[1]

        d60 = 60./180.*math.pi
        ang = math.atan2(yw, xw/2.)
        if ang > d60:
            # taller than wider
            widthh = xw/2
            height = math.tan(d60) * widthh
        else:
            # wider than taller
            height = yw
            widthh = height / math.tan(d60)

        # box for equilateral triangle
        self._box = ( (bounds[2]+bounds[0])/2 - widthh,
                      (bounds[1]+bounds[3])/2 - height/2,
                      (bounds[2]+bounds[0])/2 + widthh,
                      (bounds[1]+bounds[3])/2 + height/2 )
        self._width = widthh*2
        self._height = height

        # triangle shaped polygon for graph
        self._tripoly = p = qt4.QPolygonF()
        p.append( qt4.QPointF(self._box[0], self._box[3]) )
        p.append( qt4.QPointF(self._box[0]+widthh, self._box[1]) )
        p.append( qt4.QPointF(self._box[2], self._box[3]) )

        path = qt4.QPainterPath()
        path.addPolygon(p)
        path.closeSubpath()
        utils.brushExtFillPath(painter, s.Background, path,
                               stroke=s.Border.makeQPenWHide(painter))

        # work out origins and size
        self._size = max(min(s.fracsize, 1.), 0.)

        # make sure we don't go past the ends of the allowed range
        # value of origin of left axis at top
        self._orgleft = min(s.originleft, 1.-self._size)
        # value of origin of bottom axis at left
        self._orgbot = min(s.originbottom, 1.-self._size)
        # origin of right axis at bottom
        self._orgright = 1. - self._orgleft - (self._orgbot + self._size)
Exemple #10
0
    def render(self, state):
        initx = state.x

        # draw material under bar
        Part.render(self, state)

        # draw line over text with 0.5pt thickness
        painter = state.painter
        height = state.fontMetrics().ascent()

        painter.save()
        penw = state.getPixelsPerPt() * 0.5
        painter.setPen(qt4.QPen(painter.pen().brush(), penw))
        painter.drawLine(qt4.QPointF(initx, state.y - height + penw),
                         qt4.QPointF(state.x, state.y - height + penw))
        painter.restore()
Exemple #11
0
    def __init__(self, params):
        qt4.QGraphicsRectItem.__init__(self,
                                       params.posn[0], params.posn[1],
                                       params.dims[0], params.dims[1])
        self.params = params

        self.setCursor(qt4.Qt.SizeAllCursor)
        self.setZValue(1.)
        self.setFlag(qt4.QGraphicsItem.ItemIsMovable)
        self.highlightpen = qt4.QPen(qt4.Qt.red, 2, qt4.Qt.DotLine)

        pposn, dims = params.parentposn, params.dims
        th = params.textheight

        # special places on the plot
        xposn = {
            'left':   pposn[0] + th,
            'centre': pposn[0] + 0.5*(pposn[2]-pposn[0]-dims[0]),
            'right':  pposn[2] - th - dims[0]
            }
        yposn = {
            'top':    pposn[1] + th,
            'centre': pposn[1] + 0.5*(pposn[3]-pposn[1]-dims[1]),
            'bottom': pposn[3] - th - dims[1]
            }

        # these are special places where the key is aligned
        self.highlightpoints = {}
        for xname, xval in xposn.iteritems():
            for yname, yval in yposn.iteritems():
                self.highlightpoints[(xname, yname)] = qt4.QPointF(xval, yval)

        self.updatePen()
Exemple #12
0
    def updateCornerPosns(self):
        """Update all corners from updated box."""

        par = self.params
        pos = par.posn
        # update cursors
        self.corners[0].setCursor(qt4.Qt.SizeFDiagCursor)
        self.corners[1].setCursor(qt4.Qt.SizeBDiagCursor)
        self.corners[2].setCursor(qt4.Qt.SizeBDiagCursor)
        self.corners[3].setCursor(qt4.Qt.SizeFDiagCursor)

        # trim box to maximum size
        pos[0] = max(pos[0], par.maxposn[0])
        pos[1] = max(pos[1], par.maxposn[1])
        pos[2] = min(pos[2], par.maxposn[2])
        pos[3] = min(pos[3], par.maxposn[3])

        # move corners
        for corner, (xindex, yindex) in itertools.izip(self.corners,
                                                       self.mapcornertoposn):
            corner.setPos(qt4.QPointF(pos[xindex], pos[yindex]))

        # move lines
        w, h = pos[2] - pos[0], pos[3] - pos[1]
        self.lines[0].setPos(pos[0], pos[1])
        self.lines[0].setLine(0, 0, w, 0)
        self.lines[1].setPos(pos[2], pos[1])
        self.lines[1].setLine(0, 0, 0, h)
        self.lines[2].setPos(pos[2], pos[3])
        self.lines[2].setLine(0, 0, -w, 0)
        self.lines[3].setPos(pos[0], pos[3])
        self.lines[3].setLine(0, 0, 0, -h)
Exemple #13
0
    def render(self):
        """Render the text."""

        if self.calcbounds is None:
            self.getBounds()

        state = RenderState(self.font, self.painter, self.xi, self.yi,
                            self.alignhorz)

        # if the text is rotated, change the coordinate frame
        if self.angle != 0:
            self.painter.save()
            self.painter.translate(qt4.QPointF(state.x, state.y))
            self.painter.rotate(self.angle)
            state.x = 0
            state.y = 0

        # actually paint the string
        self.painter.setFont(self.font)
        self.parttree.render(state)

        # restore coordinate frame if text was rotated
        if self.angle != 0:
            self.painter.restore()

        # caller might want this information
        return self.calcbounds
Exemple #14
0
def _errorBarsDiamond(style, xmin, xmax, ymin, ymax, xplotter, yplotter, s,
                      painter, clip):
    """Draw diamond around error region."""
    if None not in (xmin, xmax, ymin, ymax):

        # expand clip by pen width (urgh)
        pw = painter.pen().widthF() * 2
        clip = qt4.QRectF(qt4.QPointF(clip.left() - pw,
                                      clip.top() - pw),
                          qt4.QPointF(clip.right() + pw,
                                      clip.bottom() + pw))

        path = qt4.QPainterPath()
        utils.addNumpyPolygonToPath(path, clip, xmin, yplotter, xplotter, ymax,
                                    xmax, yplotter, xplotter, ymin)
        painter.setBrush(qt4.QBrush())
        painter.drawPath(path)
Exemple #15
0
    def clipAxesBounds(self, axes, bounds):
        """Returns clipping rectange for start and stop values of axis."""

        # update cached coordinates of axes
        axes[0].plotterToDataCoords(bounds, N.array([]))
        axes[1].plotterToDataCoords(bounds, N.array([]))

        # get range
        x1, x2 = axes[0].coordParr1, axes[0].coordParr2
        if x1 > x2:
            x1, x2 = x2, x1
        y1, y2 = axes[1].coordParr2, axes[1].coordParr1
        if y1 > y2:
            y1, y2 = y2, y1

        # actually clip the data
        cliprect = qt4.QRectF(qt4.QPointF(x1, y1), qt4.QPointF(x2, y2))
        return cliprect
Exemple #16
0
    def plotBars(self, painter, s, dsnum, clip, corners):
        """Plot a set of boxes."""
        # get style
        brush = s.BarFill.get('fills').returnBrushExtended(dsnum)
        pen = s.BarLine.get('lines').makePen(painter, dsnum)
        lw = pen.widthF() * 2

        # make clip box bigger to avoid lines showing
        extclip = qt4.QRectF(
            qt4.QPointF(clip.left() - lw,
                        clip.top() - lw),
            qt4.QPointF(clip.right() + lw,
                        clip.bottom() + lw))

        # plot bars
        path = qt4.QPainterPath()
        utils.addNumpyPolygonToPath(path, extclip, corners[0], corners[1],
                                    corners[2], corners[1], corners[2],
                                    corners[3], corners[0], corners[3])
        utils.brushExtFillPath(painter, brush, path, stroke=pen)
Exemple #17
0
    def render(self, state):
        """Render some text."""

        width = state.fontMetrics().width(self.text)

        # actually write the text if requested
        if state.actually_render:
            state.painter.drawText(qt4.QPointF(state.x, state.y), self.text)

        # move along, nothing to see
        state.x += width
Exemple #18
0
    def render(self, state):
        initx = state.x

        # draw material under bar
        Part.render(self, state)

        # draw circle over text with 1pt radius
        painter = state.painter
        height = state.fontMetrics().ascent()

        painter.save()
        circsize = state.getPixelsPerPt()
        painter.setBrush(qt4.QBrush(painter.pen().color()))
        painter.setPen(qt4.QPen(qt4.Qt.NoPen))

        x = 0.5 * (initx + state.x)
        y = state.y - height + circsize
        painter.drawEllipse(
            qt4.QRectF(qt4.QPointF(x - circsize, y - circsize),
                       qt4.QPointF(x + circsize, y + circsize)))
        painter.restore()
Exemple #19
0
    def drawFillPts(self, painter, brushext, cliprect, ptsx, ptsy):
        '''Draw points for plotting a fill.'''
        pts = qt4.QPolygonF()
        utils.addNumpyToPolygonF(pts, ptsx, ptsy)

        filltype = brushext.filltype
        # this is broken: FIXME
        if filltype == 'left':
            dyend = ptsy[-1]-self._box[1]
            pts.append( qt4.QPointF(ptsx[-1]-dyend*tan30, self._box[1]) )
            dystart = ptsy[0]-self._box[1]
            pts.append( qt4.QPointF(ptsx[0]-dystart*tan30, self._box[1]) )
        elif filltype == 'right':
            pts.append( qt4.QPointF(self._box[2], ptsy[-1]) )
            pts.append( qt4.QPointF(self._box[2], ptsy[0]) )
        elif filltype == 'bottom':
            dyend = self._box[3]-ptsy[-1]
            pts.append( qt4.QPointF(ptsx[-1]-dyend*tan30, self._box[3]) )
            dystart = self._box[3]-ptsy[0]
            pts.append( qt4.QPointF(ptsx[0]-dystart*tan30, self._box[3]) )
        elif filltype == 'polygon':
            pass
        else:
            pts = None

        if pts is not None:
            utils.brushExtFillPolygon(painter, brushext, cliprect, pts)
Exemple #20
0
    def drawGraph(self, painter, bounds, datarange, outerbounds=None):
        '''Plot graph area and axes.'''

        s = self.settings
        if s.maxradius == 'Auto':
            self._maxradius = datarange[1]
        else:
            self._maxradius = s.maxradius

        self._xscale = (bounds[2] - bounds[0]) * 0.5
        self._yscale = (bounds[3] - bounds[1]) * 0.5
        self._xc = 0.5 * (bounds[0] + bounds[2])
        self._yc = 0.5 * (bounds[3] + bounds[1])

        path = qt4.QPainterPath()
        path.addEllipse(
            qt4.QRectF(qt4.QPointF(bounds[0], bounds[1]),
                       qt4.QPointF(bounds[2], bounds[3])))
        utils.brushExtFillPath(painter,
                               s.Background,
                               path,
                               stroke=s.Border.makeQPenWHide(painter))
Exemple #21
0
    def _getBezierLine(self, poly):
        """Try to draw a bezier line connecting the points."""

        npts = qtloops.bezier_fit_cubic_multi(poly, 0.1, len(poly) + 1)
        i = 0
        path = qt4.QPainterPath()
        lastpt = qt4.QPointF(-999999, -999999)
        while i < len(npts):
            if lastpt != npts[i]:
                path.moveTo(npts[i])
            path.cubicTo(npts[i + 1], npts[i + 2], npts[i + 3])
            lastpt = npts[i + 3]
            i += 4
        return path
Exemple #22
0
    def draw(self, posn, phelper, outerbounds=None):
        """Plot the data on a plotter."""

        s = self.settings

        # exit if hidden
        if s.hide:
            return

        # get points in plotter coordinates
        xp, yp = self._getPlotterCoords(posn)
        if xp is None or yp is None:
            # we can't calculate coordinates
            return

        x1, y1, x2, y2 = posn
        cliprect = qt4.QRectF(qt4.QPointF(x1, y1), qt4.QPointF(x2, y2))
        painter = phelper.painter(self, posn, clip=cliprect)

        pen = s.Line.makeQPenWHide(painter)
        pw = pen.widthF() * 2
        lineclip = qt4.QRectF(qt4.QPointF(x1 - pw, y1 - pw),
                              qt4.QPointF(x2 + pw, y2 + pw))

        # this is a hack as we generate temporary fake datasets
        path = qt4.QPainterPath()
        for xvals, yvals in document.generateValidDatasetParts(
                document.Dataset(xp), document.Dataset(yp)):

            poly = qt4.QPolygonF()
            utils.addNumpyToPolygonF(poly, xvals.data, yvals.data)
            clippedpoly = qt4.QPolygonF()
            utils.polygonClip(poly, lineclip, clippedpoly)
            path.addPolygon(clippedpoly)
            path.closeSubpath()

        utils.brushExtFillPath(painter, s.Fill, path, stroke=pen)
Exemple #23
0
    def draw(self, parentposn, painthelper, outerbounds=None):
        """Draw the plotter. Clip graph inside bounds."""

        # document should pass us the page bounds
        x1, y1, x2, y2 = parentposn

        # find ranges of axes
        axisdependhelper = _AxisDependHelper(self)
        axisdependhelper.findPlotters()
        axisdependhelper.findAxisRanges()

        # store axis->plotter mappings in painter too (is this nasty?)
        painthelper.axisplottermap.update(axisdependhelper.axis_plotter_map)

        if self.settings.hide:
            bounds = self.computeBounds(parentposn, painthelper)
            return bounds

        clip = qt4.QRectF(qt4.QPointF(parentposn[0], parentposn[1]),
                          qt4.QPointF(parentposn[2], parentposn[3]))
        painter = painthelper.painter(self, parentposn, clip=clip)

        # clip to page
        bounds = widget.Widget.draw(self, parentposn, painthelper, parentposn)

        # w and h are non integer
        w = self.settings.get('width').convert(painter)
        h = self.settings.get('height').convert(painter)
        painthelper.setControlGraph(self, [
            controlgraph.ControlMarginBox(self, [0, 0, w, h],
                                          [-10000, -10000, 10000, 10000],
                                          painthelper,
                                          ismovable=False)
        ])

        return bounds
Exemple #24
0
    def drawFillPts(self, painter, extfill, cliprect, ptsx, ptsy):
        '''Draw points for plotting a fill.'''
        pts = qt4.QPolygonF()
        utils.addNumpyToPolygonF(pts, ptsx, ptsy)

        filltype = extfill.filltype
        if filltype == 'center':
            pts.append(qt4.QPointF(self._xc, self._yc))
            utils.brushExtFillPolygon(painter, extfill, cliprect, pts)
        elif filltype == 'outside':
            pp = qt4.QPainterPath()
            pp.moveTo(self._xc, self._yc)
            pp.arcTo(cliprect, 0, 360)
            pp.addPolygon(pts)
            utils.brushExtFillPath(painter, extfill, pp)
        elif filltype == 'polygon':
            utils.brushExtFillPolygon(painter, extfill, cliprect, pts)
Exemple #25
0
    def _fillRegion(self, painter, pxpts, pypts, bounds, belowleft, clip,
                    brush):
        """Fill the region above/below or left/right of the points.

        belowleft fills below if the variable is 'x', or left if 'y'
        otherwise it fills above/right."""

        # find starting and ending points for the filled region
        x1, y1, x2, y2 = bounds

        pts = qt4.QPolygonF()
        if self.settings.variable == 'x':
            if belowleft:
                pts.append(qt4.QPointF(pxpts[0], y2))
                endpt = qt4.QPointF(pxpts[-1], y2)
            else:
                pts.append(qt4.QPointF(pxpts[0], y1))
                endpt = qt4.QPointF(pxpts[-1], y1)
        else:
            if belowleft:
                pts.append(qt4.QPointF(x1, pypts[0]))
                endpt = qt4.QPointF(x1, pypts[-1])
            else:
                pts.append(qt4.QPointF(x2, pypts[0]))
                endpt = qt4.QPointF(x2, pypts[-1])

        # add the points between
        utils.addNumpyToPolygonF(pts, pxpts, pypts)

        # stick on the ending point
        pts.append(endpt)

        # draw the clipped polygon
        clipped = qt4.QPolygonF()
        utils.polygonClip(pts, clip, clipped)
        path = qt4.QPainterPath()
        path.addPolygon(clipped)
        utils.brushExtFillPath(painter, brush, path)
Exemple #26
0
    def render(self, state):
        if len(self.children) != 2:
            return

        font = state.font
        painter = state.painter

        # make font half size
        size = font.pointSizeF()
        font.setPointSizeF(size * 0.5)
        painter.setFont(font)

        # keep track of width above and below line
        if not state.actually_render:
            self.widths = []

        initx = state.x
        inity = state.y

        # render bottom of fraction
        if state.actually_render and len(self.widths) == 2:
            # centre line
            state.x = initx + (max(self.widths) - self.widths[0]) * 0.5
        self.children[1].render(state)
        if not state.actually_render:
            # get width if not rendering
            self.widths.append(state.x - initx)

        # render top of fraction
        m = state.fontMetrics()
        state.y -= (m.ascent() + m.descent())
        if state.actually_render and len(self.widths) == 2:
            # centre line
            state.x = initx + (max(self.widths) - self.widths[1]) * 0.5
        else:
            state.x = initx
        self.children[0].render(state)
        if not state.actually_render:
            self.widths.append(state.x - initx)

        state.x = initx + max(self.widths)
        state.y = inity

        # restore font
        font.setPointSizeF(size)
        painter.setFont(font)
        height = state.fontMetrics().ascent()

        # draw line between lines with 0.5pt thickness
        painter.save()
        pen = painter.pen()
        painter.setPen(
            qt4.QPen(painter.pen().brush(),
                     state.getPixelsPerPt() * 0.5))
        painter.setPen(pen)

        painter.drawLine(
            qt4.QPointF(initx, inity - height / 2.),
            qt4.QPointF(initx + max(self.widths), inity - height / 2))

        painter.restore()
Exemple #27
0
    def _getLinePoints(self, xvals, yvals, posn, xdata, ydata):
        """Get the points corresponding to the line connecting the points."""

        pts = qt4.QPolygonF()

        s = self.settings
        steps = s.PlotLine.steps

        # simple continuous line
        if steps == 'off':
            utils.addNumpyToPolygonF(pts, xvals, yvals)

        # stepped line, with points on left
        elif steps[:4] == 'left':
            x1 = xvals[:-1]
            x2 = xvals[1:]
            y1 = yvals[:-1]
            y2 = yvals[1:]
            utils.addNumpyToPolygonF(pts, x1, y1, x2, y1, x2, y2)

        # stepped line, with points on right
        elif steps[:5] == 'right':
            x1 = xvals[:-1]
            x2 = xvals[1:]
            y1 = yvals[:-1]
            y2 = yvals[1:]
            utils.addNumpyToPolygonF(pts, x1, y1, x1, y2, x2, y2)

        # stepped line, with points in centre
        # this is complex as we can't use the mean of the plotter coords,
        #  as the axis could be log
        elif steps[:6] == 'centre':
            axes = self.parent.getAxes((s.xAxis, s.yAxis))

            if xdata.hasErrors():
                # Special case if error bars on x points:
                # here we use the error bars to define the steps
                xmin, xmax = xdata.getPointRanges()

                # this is duplicated from drawing error bars: bad
                # convert xmin and xmax to graph coordinates
                xmin = axes[0].dataToPlotterCoords(posn, xmin)
                xmax = axes[0].dataToPlotterCoords(posn, xmax)
                utils.addNumpyToPolygonF(pts, xmin, yvals, xmax, yvals)

            else:
                # we put the bin edges half way between the points
                # we assume this is the correct thing to do even in log space
                x1 = xvals[:-1]
                x2 = xvals[1:]
                y1 = yvals[:-1]
                y2 = yvals[1:]
                xc = 0.5 * (x1 + x2)
                utils.addNumpyToPolygonF(pts, x1, y1, xc, y1, xc, y2)

                if len(xvals) > 0:
                    pts.append(qt4.QPointF(xvals[-1], yvals[-1]))

        else:
            assert False

        return pts
Exemple #28
0
    def draw(self, posn, phelper, outerbounds = None):
        """Plot the key on a plotter."""

        s = self.settings
        d = self.document
        if s.hide:
            return

        # if a dataset is used, we can't use control items
        isnotdataset = ( not s.get('xPos').isDataset(d) and 
                         not s.get('yPos').isDataset(d) )

        if s.mode == 'length-angle':
            isnotdataset = ( isnotdataset and
                             not s.get('length').isDataset(d) and
                             not s.get('angle').isDataset(d) )
        else:
            isnotdataset = ( isnotdataset and
                             not s.get('xPos2').isDataset(d) and
                             not s.get('yPos2').isDataset(d) )

        # now do the drawing
        clip = None
        if s.clip:
            clip = qt4.QRectF( qt4.QPointF(posn[0], posn[1]),
                               qt4.QPointF(posn[2], posn[3]) )
        painter = phelper.painter(self, posn, clip=clip)

        # adjustable positions for the lines
        arrowsize = s.get('arrowSize').convert(painter)

        # drawing settings for line
        if not s.Line.hide:
            painter.setPen( s.get('Line').makeQPen(painter) )
        else:
            painter.setPen( qt4.QPen(qt4.Qt.NoPen) )

        # settings for fill
        if not s.Fill.hide:
            painter.setBrush( s.get('Fill').makeQBrush() )
        else:
            painter.setBrush( qt4.QBrush() )

        # iterate over positions
        scaling = posn[2]-posn[0]
        if s.mode == 'length-angle':
            lines = self._computeLinesLengthAngle(posn, scaling)
        else:
            lines = self._computeLinesPointToPoint(posn)

        if lines is None:
            return

        controlgraphitems = []
        for index, (x, y, l, a) in enumerate(lines):

            utils.plotLineArrow(painter, x, y, l, a,
                                arrowsize=arrowsize,
                                arrowleft=s.arrowleft,
                                arrowright=s.arrowright)

            if isnotdataset:
                cgi = controlgraph.ControlLine(
                    self, x, y,
                    x + l*math.cos(a/180.*math.pi),
                    y + l*math.sin(a/180.*math.pi))
                cgi.index = index
                cgi.widgetposn = posn
                controlgraphitems.append(cgi)

        phelper.setControlGraph(self, controlgraphitems)
Exemple #29
0
    def draw(self, posn, phelper, outerbounds=None):
        """Plot the key on a plotter."""

        s = self.settings
        d = self.document
        if s.hide:
            return

        # get positions of shapes
        width = s.get('width').getFloatArray(d)
        height = s.get('height').getFloatArray(d)
        rotate = s.get('rotate').getFloatArray(d)
        if width is None or height is None or rotate is None:
            return

        # translate coordinates from axes or relative values
        xpos, ypos = self._getPlotterCoords(posn)
        if xpos is None or ypos is None:
            # we can't calculate coordinates
            return

        # if a dataset is used, we can't use control items
        isnotdataset = (not s.get('xPos').isDataset(d)
                        and not s.get('yPos').isDataset(d)
                        and not s.get('width').isDataset(d)
                        and not s.get('height').isDataset(d)
                        and not s.get('rotate').isDataset(d))
        controlgraphitems = []

        clip = None
        if s.clip:
            clip = qt4.QRectF(qt4.QPointF(posn[0], posn[1]),
                              qt4.QPointF(posn[2], posn[3]))
        painter = phelper.painter(self, posn, clip=clip)

        # drawing settings for shape
        if not s.Border.hide:
            painter.setPen(s.get('Border').makeQPen(painter))
        else:
            painter.setPen(qt4.QPen(qt4.Qt.NoPen))

        # iterate over positions
        index = 0
        dx, dy = posn[2] - posn[0], posn[3] - posn[1]
        for x, y, w, h, r in itertools.izip(xpos, ypos, itertools.cycle(width),
                                            itertools.cycle(height),
                                            itertools.cycle(rotate)):
            wp, hp = dx * w, dy * h
            painter.save()
            painter.translate(x, y)
            if r != 0:
                painter.rotate(r)
            self.drawShape(painter, qt4.QRectF(-wp * 0.5, -hp * 0.5, wp, hp))
            painter.restore()

            if isnotdataset:
                cgi = controlgraph.ControlResizableBox(self, [x, y], [wp, hp],
                                                       r,
                                                       allowrotate=True)
                cgi.index = index
                cgi.widgetposn = posn
                index += 1
                controlgraphitems.append(cgi)

        phelper.setControlGraph(self, controlgraphitems)
Exemple #30
0
 def swapline(self, painter, a1, b1, a2, b2):
     """Draw line, but swap x & y coordinates if vertical axis."""
     if self.settings.direction == 'horizontal':
         painter.drawLine(qt4.QPointF(a1, b1), qt4.QPointF(a2, b2))
     else:
         painter.drawLine(qt4.QPointF(b1, a1), qt4.QPointF(b2, a2))