Esempio n. 1
0
 def _coordinate_transform(self, input: QRectF, output: QRectF):
     rx, ry = output.width() / input.width(), output.height(
     ) / input.height()
     t = QTransform.fromTranslate(-input.left(), -input.top())
     t *= QTransform.fromScale(rx, ry)
     t *= QTransform.fromTranslate(output.left(), output.top())
     return t
Esempio n. 2
0
    def set_scale(self, sx, sy, px, py):
        m = QTransform.fromTranslate(-px, -py)
        m = QTransform.fromScale(sx, sy) * m
        m = QTransform.fromTranslate(px, py) * m

        m = self._tmove * m
        self._tmove = m
Esempio n. 3
0
def ParseTransformAttrib(s):
    # where s is an SVG transform attribute such as "translate(-2,1) matrix(0 1 2 3 4 5)"
    # return a list of QTransforms
    xforms = []
    s = s.lower()
    while s:
        s = re.sub(r'^\s+,?\s+', '', s)  # remove leading WS,WS
        m = re.match(r'\s*(\w+)\s*\(((\s*[0-9e.+-]+\s*,?)+)\)',
                     s)  # match identifier(numbers) clause
        if m:
            values = SplitFloatValues(m.group(2))
            if m.group(1) == 'translate':
                if len(values) == 1: values.append(0)
                xforms.append(QTransform.fromTranslate(*values))
            elif m.group(1) == 'scale':
                if len(values) == 1: values.append(values[0])
                xforms.append(QTransform.fromScale(*values))
            elif m.group(1) == 'rotate':
                xforms.append(QTransform().rotate(
                    values[0]))  # TODO: handle cx,cy values
            elif m.group(1) == 'matrix':
                logger.trace('matrix({}): m.group(2) = {}', values, m.group(2))
                xforms.append(
                    QTransform(values[0], values[1], 0, values[2], values[3],
                               0, values[4], values[5], 1))
            # TODO: handle skewX and skewY
            else:
                logger.warning('unrecognized transform: {}', m.group())
            s = s[m.end() + 1:]
        else:
            if s: logger.warning('unparsed transform: {}', s)
            break
    return xforms
Esempio n. 4
0
def ParseTransformAttrib(s):
  # where s is an SVG transform attribute such as "translate(-2,1) matrix(0 1 2 3 4 5)"
  # return a list of QTransforms
  xforms = []
  s = s.lower()
  while s:
    s = re.sub(r'^\s+,?\s+', '', s)  # remove leading WS,WS
    m = re.match(r'\s*(\w+)\s*\(((\s*[0-9e.+-]+\s*,?)+)\)', s) # match identifier(numbers) clause
    if m:
      values = SplitFloatValues(m.group(2))
      if m.group(1) == 'translate':
        if len(values) == 1: values.append(0)
        xforms.append( QTransform.fromTranslate(*values) )
      elif m.group(1) == 'scale':
        if len(values) == 1: values.append(values[0])
        xforms.append( QTransform.fromScale(*values) )
      elif m.group(1) == 'rotate':
        xforms.append( QTransform().rotate(values[0]) )  # TODO: handle cx,cy values
      elif m.group(1) == 'matrix':
        logger.trace('matrix({}): m.group(2) = {}', values, m.group(2))
        xforms.append( QTransform( values[0], values[1], 0
                                 , values[2], values[3], 0
                                 , values[4], values[5], 1) )
      # TODO: handle skewX and skewY
      else: logger.warning('unrecognized transform: {}', m.group())
      s = s[m.end()+1:]
    else:
      if s: logger.warning('unparsed transform: {}', s)
      break
  return xforms
Esempio n. 5
0
    def _newAxes(self):
        """Given self._rotation and self._swapped, calculates and sets
        the appropriate data2scene transformation.

        """
        # TODO: this function works, but it is not elegant. There must
        # be a simpler way to calculate the appropriate transformation.

        w, h = self.dataShape
        assert self._rotation in range(0, 4)

        # unlike self._rotation, the local variable 'rotation'
        # indicates how many times to rotate clockwise after swapping
        # axes.

        # t1 : do axis swap
        t1 = QTransform()
        if self._swapped:
            t1 = QTransform(0, 1, 0, 1, 0, 0, 0, 0, 1)
            h, w = w, h

        # t2 : do rotation
        t2 = QTransform()
        t2.rotate(self._rotation * 90)

        # t3: shift to re-center
        rot2trans = {0: (0, 0), 1: (h, 0), 2: (w, h), 3: (0, w)}

        trans = rot2trans[self._rotation]
        t3 = QTransform.fromTranslate(*trans)

        self.data2scene = t1 * t2 * t3
        if self._tileProvider:
            self._tileProvider.axesSwapped = self._swapped
        self.axesChanged.emit(self._rotation, self._swapped)
Esempio n. 6
0
    def _prepare_drawing_cache(self, config: "ExtraDrawConfig"):
        """
        生成一个矩阵用以将painter的坐标系从UI坐标系调整为drawer坐标系
        这样painter中的x和y轴就正好对应数据的x和y了
        """
        # 从UI坐标系到drawer坐标系的转化矩阵的构造顺序恰好相反,假设目前为drawer坐标系
        # 将drawer坐标转化为UI坐标
        drawer_area = QRectF(
            config.begin,
            config.y_low,
            max(config.end - config.begin, 1),
            max(config.y_high - config.y_low, 1),
        )
        plot_area = self.plot_area()
        if plot_area.width() <= 0 or plot_area.height() <= 0:
            raise NoVisualAreaError()

        # 应用这个坐标转化
        transform = self._coordinate_transform(drawer_area, plot_area)

        # 去除padding对上下翻转的影响
        transform *= QTransform.fromTranslate(0, -plot_area.top())

        # 在UI坐标系中上下翻转图像
        transform *= QTransform.fromTranslate(0, -plot_area.height())
        transform *= QTransform().rotate(180, Qt.XAxis)

        # 恢复padding
        transform *= QTransform.fromTranslate(0, plot_area.top())

        # 保存一些中间变量
        drawing_cache = DrawingCache()
        drawing_cache.drawer_transform = transform
        drawing_cache.ui_transform = transform.inverted()[0]
        drawing_cache.drawer_area = drawer_area
        # drawing_cache.drawer_area_width = drawer_area.width()
        # drawing_cache.drawer_area_height = drawer_area.height()
        drawing_cache.plot_area = plot_area
        # drawing_cache.plot_area_width = plot_area.width()
        # drawing_cache.plot_area_height = plot_area.height()

        drawing_cache.p2d_w = drawer_area.width() / plot_area.width()
        drawing_cache.p2d_h = drawer_area.height() / plot_area.height()

        config.drawing_cache = drawing_cache
Esempio n. 7
0
    def _fetch_tile_layer(self, timestamp, ims, transform, tile_nr, stack_id, ims_req, cache):
        """
        Fetch a single tile from a layer (ImageSource).

        Parameters
        ----------
        timestamp
            The timestamp at which ims_req was created
        ims
            The layer (image source) we're fetching from
        transform
            The transform to apply to the fetched data, before storing it in the cache
        tile_nr
            The ID of the fetched tile
        stack_id
            The stack ID of the tile we're fetching (e.g. which T-slice and Z-slice this tile belongs to)
        ims_req
            A request object (e.g. GrayscaleImageRequest) with a wait() method that produces an item of
            the appropriate type for the layer (i.e. either a QImage or a QGraphicsItem)
        cache
            The value of self._cache at the time the ims_req was created.
            (The cache can be replaced occasionally. See TileProvider._onSizeChanged().)
        """
        try:
            try:
                with cache:
                    layerTimestamp = cache.layerTimestamp(stack_id, ims, tile_nr)
            except KeyError:
                # May not be a timestamp yet (especially when prefetching)
                layerTimestamp = 0

            tile_rect = QRectF(self.tiling.imageRects[tile_nr])

            if timestamp > layerTimestamp:
                img = ims_req.wait()
                if isinstance(img, QImage):
                    img = img.transformed(transform)
                elif isinstance(img, QGraphicsItem):
                    # FIXME: It *seems* like applying the same transform to QImages and QGraphicsItems
                    #        makes sense here, but for some strange reason it isn't right.
                    #        For QGraphicsItems, it seems obvious that this is the correct transform.
                    #        I do not understand the formula that produces 'transform', which is used for QImage tiles.
                    img.setTransform(QTransform.fromTranslate(tile_rect.left(), tile_rect.top()), combine=True)
                    img.setTransform(self.tiling.data2scene, combine=True)
                else:
                    assert False, "Unexpected image type: {}".format(type(img))

                with cache:
                    try:
                        cache.updateTileIfNecessary(stack_id, ims, tile_nr, timestamp, img)
                    except KeyError:
                        pass

                if stack_id == self._current_stack_id and cache is self._cache:
                    self.sceneRectChanged.emit(tile_rect)
        except BaseException:
            logger.debug("Failed to fetch layer tile", exc_info=True)
Esempio n. 8
0
    def _fetch_tile_layer(self, timestamp, ims, transform, tile_nr, stack_id, ims_req, cache):
        """
        Fetch a single tile from a layer (ImageSource).

        Parameters
        ----------
        timestamp
            The timestamp at which ims_req was created
        ims
            The layer (image source) we're fetching from
        transform
            The transform to apply to the fetched data, before storing it in the cache
        tile_nr
            The ID of the fetched tile
        stack_id
            The stack ID of the tile we're fetching (e.g. which T-slice and Z-slice this tile belongs to)
        ims_req
            A request object (e.g. GrayscaleImageRequest) with a wait() method that produces an item of
            the appropriate type for the layer (i.e. either a QImage or a QGraphicsItem)
        cache
            The value of self._cache at the time the ims_req was created.
            (The cache can be replaced occasionally. See TileProvider._onSizeChanged().)
        """
        try:
            try:
                with cache:
                    layerTimestamp = cache.layerTimestamp(stack_id, ims, tile_nr)
            except KeyError:
                # May not be a timestamp yet (especially when prefetching)
                layerTimestamp = 0

            tile_rect = QRectF(self.tiling.imageRects[tile_nr])

            if timestamp > layerTimestamp:
                img = ims_req.wait()
                if isinstance(img, QImage):
                    img = img.transformed(transform)
                elif isinstance(img, QGraphicsItem):
                    # FIXME: It *seems* like applying the same transform to QImages and QGraphicsItems
                    #        makes sense here, but for some strange reason it isn't right.
                    #        For QGraphicsItems, it seems obvious that this is the correct transform.
                    #        I do not understand the formula that produces 'transform', which is used for QImage tiles.
                    img.setTransform(QTransform.fromTranslate(tile_rect.left(), tile_rect.top()), combine=True)
                    img.setTransform(self.tiling.data2scene, combine=True)
                else:
                    assert False, "Unexpected image type: {}".format(type(img))

                with cache:
                    try:
                        cache.updateTileIfNecessary(stack_id, ims, tile_nr, timestamp, img)
                    except KeyError:
                        pass

                if stack_id == self._current_stack_id and cache is self._cache:
                    self.sceneRectChanged.emit(tile_rect)
        except BaseException:
            sys.excepthook(*sys.exc_info())
Esempio n. 9
0
    def timerEvent(self, event):
        axelDistance = 54.0
        wheelsAngleRads = (self.wheelsAngle * math.pi) / 180
        turnDistance = math.cos(wheelsAngleRads) * axelDistance * 2
        turnRateRads = wheelsAngleRads / turnDistance
        turnRate = (turnRateRads * 180) / math.pi
        rotation = self.speed * turnRate

        self.setTransform(QTransform().rotate(rotation), True)
        self.setTransform(QTransform.fromTranslate(0, -self.speed), True)
        self.update()
Esempio n. 10
0
def objectTransform(object, renderer):
    transform = QTransform()
    if (object.rotation() != 0):
        pos = renderer.pixelToScreenCoords_(object.position())
        transform = rotateAt(pos, object.rotation())

    offset = object.objectGroup().offset()
    if not offset.isNull():
        transform *= QTransform.fromTranslate(offset.x(), offset.y())

    return transform
Esempio n. 11
0
    def __init__(self, scene, width, height):
        self.width = width
        self.height = height

        self.cells = [[Cell() for j in range(self.width)]
                      for i in range(self.height)]
        for i in range(self.height):
            for j in range(self.width):
                self.cells[i][j].setTransform(
                    QTransform.fromTranslate(8 * j, 8 * i))
                scene.addItem(self.cells[i][j])
Esempio n. 12
0
    def timerEvent(self, event):
        axelDistance = 54.0
        wheelsAngleRads = (self.wheelsAngle * math.pi) / 180
        turnDistance = math.cos(wheelsAngleRads) * axelDistance * 2
        turnRateRads = wheelsAngleRads / turnDistance
        turnRate = (turnRateRads * 180) / math.pi
        rotation = self.speed * turnRate

        self.setTransform(QTransform().rotate(rotation), True)
        self.setTransform(QTransform.fromTranslate(0, -self.speed), True)
        self.update()
Esempio n. 13
0
def objectTransform(object, renderer):
    transform = QTransform()
    if (object.rotation() != 0):
        pos = renderer.pixelToScreenCoords_(object.position())
        transform = rotateAt(pos, object.rotation())

    offset = object.objectGroup().offset()
    if not offset.isNull():
        transform *= QTransform.fromTranslate(offset.x(), offset.y())
        
    return transform
Esempio n. 14
0
    def __init__(self, scene, length, color=0xFFFFFEFF, value=0):
        self.length = length
        self.color = color

        self.digits = []
        for i in range(length):
            digit = Digit(value % 10, self.color)
            digit.setTransform(
                QTransform.fromTranslate((length - i - 1) * 8, 0))
            scene.addItem(digit)
            self.digits.insert(0, digit)

            value //= 10
Esempio n. 15
0
 def update_transform(self):
     if self.transformChanged:
         translation = QTransform()
         translation = translation.fromTranslate(self.worldPosition[0],
                                                 self.worldPosition[1])
         scale = QTransform()
         scale = scale.fromScale(self.worldScale[0], self.worldScale[1])
         rot = QTransform()
         rot = rot.rotate(self.worldRotation)
         self.worldTransform = scale * rot * translation
         self.transformChanged = False
         self.update_aabb()
     return
Esempio n. 16
0
    def initScene(self):
        self.setSceneRect(0, 0, 256, 240)
        bgImage = QPixmap(resource_path('./assets/boardLayout.png'))

        self.image = self.addPixmap(bgImage)

        self.board = Board(self, 10, 20)
        self.board.translate(12 * 8, 6 * 8)

        self.top = Number(self, 6)
        self.top.translate(24 * 8, 5 * 8)

        self.score = Number(self, 6)
        self.score.translate(24 * 8, 8 * 8)

        self.lines = Number(self, 3)
        self.lines.translate(19 * 8, 3 * 8)

        self.level = Number(self, 2, value=18)
        self.level.translate(26 * 8, 21 * 8)

        self.stats = []
        for i in range(7):
            statNum = Number(self, 3, 0xFFB53120)
            statNum.translate(6 * 8, (12 + 2 * i) * 8)
            self.stats.append(statNum)

        self.statsPieces = PaletteItem(
            QPixmap(resource_path(f'./assets/pieceStats.png')))
        self.statsPieces.setTransform(QTransform.fromTranslate(24, 88))
        self.addItem(self.statsPieces)

        self.previewCoords = [(204, 119), (204, 119), (204, 119), (208, 119),
                              (204, 119), (204, 119), (208, 123)]
        self.previewType = 0
        self.preview = Piece(self.previewType, 0, 255)
        self.addItem(self.preview)
        self.preview.updateOffset(*self.previewCoords[self.previewType])

        self.cursor = CursorItem(1)
        self.addItem(self.cursor)
        self.cursor.setVisible(False)

        self.cellState = 1
        self.transparentDraw = False
        self.drawMode = False
        self.lastMousePos = None

        self.actionBuffer = ActionBuffer()
        self.actionGroup = []
Esempio n. 17
0
    def setZoom(self, zoom):
        self._zoom = zoom

        if zoom >= 1.0:
            self._zoom = 1.0

        elif zoom <= 0.1:
            self._zoom = 0.1

        transform = self.transform()
        new_transform = QTransform.fromTranslate(transform.dx(),
                                                 transform.dy())
        new_transform.scale(self._zoom, self._zoom)
        self.setTransform(new_transform)

        self.scene().setZoom(self._zoom)
Esempio n. 18
0
def compute_SMBR(geom):
    area = float("inf")
    angle = 0
    width = float("inf")
    height = float("inf")
    if (geom is None):
        return QgsGeometry()
    hull = geom.convexHull()
    if (hull.isEmpty()):
        return QgsGeometry()
    x = hull.asPolygon()
    vertexId = 0
    pt0 = x[0][vertexId]
    pt1 = pt0
    prevAngle = 0.0
    size = len(x[0])
    for vertexId in range(0, size - 0):
        pt2 = x[0][vertexId]
        currentAngle = lineAngle(pt1.x(), pt1.y(), pt2.x(), pt2.y())
        rotateAngle = 180.0 / math.pi * (currentAngle - prevAngle)
        prevAngle = currentAngle
        t = QTransform.fromTranslate(pt0.x(), pt0.y())
        t.rotate(rotateAngle)
        t.translate(-pt0.x(), -pt0.y())
        hull.transform(t)
        bounds = hull.boundingBox()
        currentArea = bounds.width() * bounds.height()
        if (currentArea < area):
            minRect = bounds
            area = currentArea
            angle = 180.0 / math.pi * currentAngle
            width = bounds.width()
            height = bounds.height()
        pt2 = pt1
    minBounds = QgsGeometry.fromRect(minRect)
    minBounds.rotate(angle, QgsPointXY(pt0.x(), pt0.y()))
    if (angle > 180.0):
        angle = math.fmod(angle, 180.0)
    return minBounds, area, angle, width, height
Esempio n. 19
0
    def paintEvent(self, _):
        """
        重写绘制事件,参考 qfusionstyle.cpp 中的 CE_ProgressBarContents 绘制方法
        """
        option = QStyleOptionProgressBar()
        self.initStyleOption(option)

        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing)
        painter.translate(0.5, 0.5)

        vertical = option.orientation == Qt.Vertical  # 是否垂直
        inverted = option.invertedAppearance  # 是否反转
        # 是否显示动画
        indeterminate = (option.minimum == option.maximum) or (
            option.minimum < option.progress < option.maximum)
        rect = option.rect

        if vertical:
            rect = QRect(rect.left(), rect.top(), rect.height(),
                         rect.width())  # 翻转宽度和高度
            m = QTransform.fromTranslate(rect.height(), 0)
            m.rotate(90.0)
            painter.setTransform(m, True)

        maxWidth = rect.width()
        progress = max(option.progress, option.minimum)
        totalSteps = max(1, option.maximum - option.minimum)
        progressSteps = progress - option.minimum
        progressBarWidth = int(progressSteps * maxWidth / totalSteps)
        width = progressBarWidth  # 已进行的进度宽度
        radius = max(1, (min(width,
                             self.width() if vertical else self.height()) //
                         4) if self._radius is None else self._radius)

        reverse = (not vertical and
                   option.direction == Qt.RightToLeft) or vertical
        if inverted:
            reverse = not reverse

        # 绘制范围
        path = QPainterPath()
        if not reverse:
            progressBar = QRectF(rect.left(), rect.top(), width, rect.height())
        else:
            progressBar = QRectF(rect.right() - width, rect.top(), width,
                                 rect.height())

        # 切割范围
        path.addRoundedRect(progressBar, radius, radius)
        painter.setClipPath(path)

        # 绘制背景颜色
        painter.setPen(Qt.NoPen)
        painter.setBrush(self._color)
        painter.drawRoundedRect(progressBar, radius, radius)

        if not indeterminate:
            if self._animation:
                self._animation.stop()
                self._animation = None
        else:
            # 叠加颜色覆盖后出现类似线条间隔的效果
            color = self._color.lighter(320)
            color.setAlpha(80)
            painter.setPen(QPen(color, self._lineWidth))

            if self._animation:
                step = int(self._animation.animationStep() % self._lineWidth)
            else:
                step = 0
                self._animation = QProgressStyleAnimation(self._fps, self)
                self._animation.start()

            # 动画斜线绘制
            startX = int(progressBar.left() - rect.height() - self._lineWidth)
            endX = int(rect.right() + self._lineWidth)

            if (not inverted and not vertical) or (inverted and vertical):
                lines = [
                    QLineF(x + step, progressBar.bottom(),
                           x + rect.height() + step, progressBar.top())
                    for x in range(startX, endX, self._lineWidth)
                ]
            else:
                lines = [
                    QLineF(x - step, progressBar.bottom(),
                           x + rect.height() - step, progressBar.top())
                    for x in range(startX, endX, self._lineWidth)
                ]
            painter.drawLines(lines)
Esempio n. 20
0
def _translate(rectsrc, rectdest, offset: QPoint) -> QTransform:
    srcfct = rectsrc.width() / rectsrc.height()
    destfct = rectdest.width() / rectdest.height()
    shiftx = rectdest.width() * max((1 - srcfct / destfct) / 2, 0)
    shifty = rectdest.height() * max((1 - destfct / srcfct) / 2, 0)
    return QTransform.fromTranslate(offset.x() + shiftx, offset.y() + shifty)
Esempio n. 21
0
 def reset_tmove(self):
     self._tmove = QTransform.fromTranslate(0, 0)
Esempio n. 22
0
 def update_translate(self, dx, dy):
     self._tmove = QTransform.fromTranslate(dx, dy)
Esempio n. 23
0
 def modelMatrix(self, center, width):
     return QTransform.fromScale(width / 239,
                                 width / 239) * QTransform.fromTranslate(
                                     -center.x(), -center.y())