예제 #1
0
파일: graphics.py 프로젝트: cdd1969/pygwa
    def paint(self, painter, option, widget=None):
        if (self.p1 == self.p2):
            return

        myPen = self.pen()
        myPen.setColor(self.myColor)
        arrowSize = self.myArrowHeadSize
        painter.setPen(myPen)
        painter.setBrush(self.myColor)

        line = QtCore.QLineF(self.p1, self.p2)

        angle = math.acos(line.dx() / line.length())
        if line.dy() >= 0:
            angle = (math.pi * 2.0) - angle

        arrowP1 = line.p2() - QtCore.QPointF(
            math.sin(angle + math.pi / 3.0) * arrowSize,
            math.cos(angle + math.pi / 3) * arrowSize)
        arrowP2 = line.p2() - QtCore.QPointF(
            math.sin(angle + math.pi - math.pi / 3.0) * arrowSize,
            math.cos(angle + math.pi - math.pi / 3.0) * arrowSize)

        self.arrowHead.clear()
        for point in [line.p2(), arrowP1, arrowP2]:
            self.arrowHead.append(point)

        painter.drawLine(line)
        painter.drawPolygon(self.arrowHead)
예제 #2
0
 def paint(self, p, opt, widget, **args):
     p.setPen(self.pen)
     line = self._line
     if line is None:
         br = self.boundingRect()
         self._line = line = QtCore.QLineF(0.0, br.bottom(), 0.0, br.top())
     p.drawLine(line)
예제 #3
0
    def transformAngle(self, relativeItem=None):
        """Return the rotation produced by this item's transform (this assumes there is no shear in the transform)
        If relativeItem is given, then the angle is determined relative to that item.
        """
        if relativeItem is None:
            relativeItem = self.parentItem()

        tr = self.itemTransform(relativeItem)
        if isinstance(tr, tuple):  ## difference between pyside and pyqt
            tr = tr[0]
        #vec = tr.map(Point(1,0)) - tr.map(Point(0,0))
        vec = tr.map(QtCore.QLineF(0, 0, 1, 0))
        #return Point(vec).angle(Point(1,0))
        return vec.angleTo(
            QtCore.QLineF(vec.p1(),
                          vec.p1() + QtCore.QPointF(1, 0)))
예제 #4
0
 def pixelHeight(self):
     ## deprecated
     vt = self.deviceTransform()
     if vt is None:
         return 0
     vt = fn.invertQTransform(vt)
     return vt.map(QtCore.QLineF(0, 0, 0, 1)).length()
예제 #5
0
파일: graphics.py 프로젝트: cdd1969/pygwa
 def updatePosition(self):
     line = QtCore.QLineF(self.p1, self.p2)
     self.setLine(line)
예제 #6
0
    def pixelVectors(self, direction=None):
        """Return vectors in local coordinates representing the width and height of a view pixel.
        If direction is specified, then return vectors parallel and orthogonal to it.
        
        Return (None, None) if pixel size is not yet defined (usually because the item has not yet been displayed)
        or if pixel size is below floating-point precision limit.
        """

        ## This is an expensive function that gets called very frequently.
        ## We have two levels of cache to try speeding things up.

        dt = self.deviceTransform()
        if dt is None:
            return None, None

        ## Ignore translation. If the translation is much larger than the scale
        ## (such as when looking at unix timestamps), we can get floating-point errors.
        dt.setMatrix(dt.m11(), dt.m12(), 0, dt.m21(), dt.m22(), 0, 0, 0, 1)

        ## check local cache
        if direction is None and dt == self._pixelVectorCache[0]:
            return tuple(map(Point,
                             self._pixelVectorCache[1]))  ## return a *copy*

        ## check global cache
        #key = (dt.m11(), dt.m21(), dt.m31(), dt.m12(), dt.m22(), dt.m32(), dt.m31(), dt.m32())
        key = (dt.m11(), dt.m21(), dt.m12(), dt.m22())
        pv = self._pixelVectorGlobalCache.get(key, None)
        if direction is None and pv is not None:
            self._pixelVectorCache = [dt, pv]
            return tuple(map(Point, pv))  ## return a *copy*

        if direction is None:
            direction = QtCore.QPointF(1, 0)
        if direction.manhattanLength() == 0:
            raise Exception("Cannot compute pixel length for 0-length vector.")

        ## attempt to re-scale direction vector to fit within the precision of the coordinate system
        ## Here's the problem: we need to map the vector 'direction' from the item to the device, via transform 'dt'.
        ## In some extreme cases, this mapping can fail unless the length of 'direction' is cleverly chosen.
        ## Example:
        ##   dt = [ 1, 0,    2
        ##          0, 2, 1e20
        ##          0, 0,    1 ]
        ## Then we map the origin (0,0) and direction (0,1) and get:
        ##    o' = 2,1e20
        ##    d' = 2,1e20  <-- should be 1e20+2, but this can't be represented with a 32-bit float
        ##
        ##    |o' - d'|  == 0    <-- this is the problem.

        ## Perhaps the easiest solution is to exclude the transformation column from dt. Does this cause any other problems?

        #if direction.x() == 0:
        #r = abs(dt.m32())/(abs(dt.m12()) + abs(dt.m22()))
        ##r = 1.0/(abs(dt.m12()) + abs(dt.m22()))
        #elif direction.y() == 0:
        #r = abs(dt.m31())/(abs(dt.m11()) + abs(dt.m21()))
        ##r = 1.0/(abs(dt.m11()) + abs(dt.m21()))
        #else:
        #r = ((abs(dt.m32())/(abs(dt.m12()) + abs(dt.m22()))) * (abs(dt.m31())/(abs(dt.m11()) + abs(dt.m21()))))**0.5
        #if r == 0:
        #r = 1.  ## shouldn't need to do this; probably means the math above is wrong?
        #directionr = direction * r
        directionr = direction

        ## map direction vector onto device
        #viewDir = Point(dt.map(directionr) - dt.map(Point(0,0)))
        #mdirection = dt.map(directionr)
        dirLine = QtCore.QLineF(QtCore.QPointF(0, 0), directionr)
        viewDir = dt.map(dirLine)
        if viewDir.length() == 0:
            return None, None  ##  pixel size cannot be represented on this scale

        ## get unit vector and orthogonal vector (length of pixel)
        #orthoDir = Point(viewDir[1], -viewDir[0])  ## orthogonal to line in pixel-space
        try:
            normView = viewDir.unitVector()
            #normView = viewDir.norm()  ## direction of one pixel orthogonal to line
            normOrtho = normView.normalVector()
            #normOrtho = orthoDir.norm()
        except:
            raise Exception("Invalid direction %s" % directionr)

        ## map back to item
        dti = fn.invertQTransform(dt)
        #pv = Point(dti.map(normView)-dti.map(Point(0,0))), Point(dti.map(normOrtho)-dti.map(Point(0,0)))
        pv = Point(dti.map(normView).p2()), Point(dti.map(normOrtho).p2())
        self._pixelVectorCache[1] = pv
        self._pixelVectorCache[0] = dt
        self._pixelVectorGlobalCache[key] = pv
        return self._pixelVectorCache[1]