⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 _lines.py

📁 Wxpython Implemented on Windows CE, Source code
💻 PY
📖 第 1 页 / 共 4 页
字号:
                self.EraseRegion(dc, region, xx, yy)
                if len(self._labelObjects) < i:
                    self._labelObjects[i].Select(False, dc)
                    self._labelObjects[i].Erase(dc)
                    self._labelObjects[i].SetSize(actualW, actualH)

                region.SetSize(actualW, actualH)

                if len(self._labelObjects) < i:
                    self._labelObjects[i].Select(True, dc)
                    self._labelObjects[i].Draw(dc)

        CentreText(dc, region.GetFormattedText(), self._xpos, self._ypos, actualW, actualH, region.GetFormatMode())
        self._formatted = True

    def DrawRegion(self, dc, region, x, y):
        """Format one region at this position."""
        if self.GetDisableLabel():
            return

        w, h = region.GetSize()

        # Get offset from x, y
        xx, yy = region.GetPosition()

        xp = xx + x
        yp = yy + y

        # First, clear a rectangle for the text IF there is any
        if len(region.GetFormattedText()):
            dc.SetPen(self.GetBackgroundPen())
            dc.SetBrush(self.GetBackgroundBrush())

            # Now draw the text
            if region.GetFont():
                dc.SetFont(region.GetFont())
                dc.DrawRectangle(xp - w / 2.0, yp - h / 2.0, w, h)

                if self._pen:
                    dc.SetPen(self._pen)
                dc.SetTextForeground(region.GetActualColourObject())

                DrawFormattedText(dc, region.GetFormattedText(), xp, yp, w, h, region.GetFormatMode())

    def EraseRegion(self, dc, region, x, y):
        """Erase one region at this position."""
        if self.GetDisableLabel():
            return

        w, h = region.GetSize()

        # Get offset from x, y
        xx, yy = region.GetPosition()

        xp = xx + x
        yp = yy + y

        if region.GetFormattedText():
            dc.SetPen(self.GetBackgroundPen())
            dc.SetBrush(self.GetBackgroundBrush())

            dc.DrawRectangle(xp - w / 2.0, yp - h / 2.0, w, h)

    def GetLabelPosition(self, position):
        """Get the reference point for a label.

        Region x and y are offsets from this.
        position is 0 (middle), 1 (start), 2 (end).
        """
        if position == 0:
            # Want to take the middle section for the label
            half_way = int(len(self._lineControlPoints) / 2.0)

            # Find middle of this line
            point = self._lineControlPoints[half_way - 1]
            next_point = self._lineControlPoints[half_way]

            dx = next_point[0] - point[0]
            dy = next_point[1] - point[1]

            return point[0] + dx / 2.0, point[1] + dy / 2.0
        elif position == 1:
            return self._lineControlPoints[0][0], self._lineControlPoints[0][1]
        elif position == 2:
            return self._lineControlPoints[-1][0], self._lineControlPoints[-1][1]

    def Straighten(self, dc = None):
        """Straighten verticals and horizontals."""
        if len(self._lineControlPoints) < 3:
            return

        if dc:
            self.Erase(dc)

        GraphicsStraightenLine(self._lineControlPoints[-1], self._lineControlPoints[-2])

        for i in range(len(self._lineControlPoints) - 2):
            GraphicsStraightenLine(self._lineControlPoints[i], self._lineControlPoints[i + 1])
                
        if dc:
            self.Draw(dc)

    def Unlink(self):
        """Unlink the line from the nodes at either end."""
        if self._to:
            self._to.GetLines().remove(self)
        if self._from:
            self._from.GetLines().remove(self)
        self._to = None
        self._from = None

    def SetEnds(self, x1, y1, x2, y2):
        """Set the end positions of the line."""
        self._lineControlPoints[0] = wx.RealPoint(x1, y1)
        self._lineControlPoints[-1] = wx.RealPoint(x2, y2)

        # Find centre point
        self._xpos = (x1 + x2) / 2.0
        self._ypos = (y1 + y2) / 2.0

    # Get absolute positions of ends
    def GetEnds(self):
        """Get the visible endpoints of the lines for drawing between two objects."""
        first_point = self._lineControlPoints[0]
        last_point = self._lineControlPoints[-1]

        return first_point[0], first_point[1], last_point[0], last_point[1]

    def SetAttachments(self, from_attach, to_attach):
        """Specify which object attachment points should be used at each end
        of the line.
        """
        self._attachmentFrom = from_attach
        self._attachmentTo = to_attach

    def HitTest(self, x, y):
        if not self._lineControlPoints:
            return False

        # Look at label regions in case mouse is over a label
        inLabelRegion = False
        for i in range(3):
            if self._regions[i]:
                region = self._regions[i]
                if len(region._formattedText):
                    xp, yp = self.GetLabelPosition(i)
                    # Offset region from default label position
                    cx, cy = region.GetPosition()
                    cw, ch = region.GetSize() 
                    cx += xp
                    cy += yp
                    
                    rLeft = cx - cw / 2.0
                    rTop = cy - ch / 2.0
                    rRight = cx + cw / 2.0
                    rBottom = cy + ch / 2.0
                    if x > rLeft and x < rRight and y > rTop and y < rBottom:
                        inLabelRegion = True
                        break

        for i in range(len(self._lineControlPoints) - 1):
            point1 = self._lineControlPoints[i]
            point2 = self._lineControlPoints[i + 1]

            # For inaccurate mousing allow 8 pixel corridor
            extra = 4

            dx = point2[0] - point1[0]
            dy = point2[1] - point1[1]

            seg_len = math.sqrt(dx * dx + dy * dy)
            if dy == 0 and dx == 0:
                continue
            distance_from_seg = seg_len * float((x - point1[0]) * dy - (y - point1[1]) * dx) / (dy * dy + dx * dx)
            distance_from_prev = seg_len * float((y - point1[1]) * dy + (x - point1[0]) * dx) / (dy * dy + dx * dx)

            if abs(distance_from_seg) < extra and distance_from_prev >= 0 and distance_from_prev <= seg_len or inLabelRegion:
                return 0, distance_from_seg

        return False

    def DrawArrows(self, dc):
        """Draw all arrows."""
        # Distance along line of each arrow: space them out evenly
        startArrowPos = 0.0
        endArrowPos = 0.0
        middleArrowPos = 0.0

        for arrow in self._arcArrows:
            ah = arrow.GetArrowEnd()
            if ah == ARROW_POSITION_START:
                if arrow.GetXOffset() and not self._ignoreArrowOffsets:
                    # If specified, x offset is proportional to line length
                    self.DrawArrow(dc, arrow, arrow.GetXOffset(), True)
                else:
                    self.DrawArrow(dc, arrow, startArrowPos, False)
                    startArrowPos += arrow.GetSize() + arrow.GetSpacing()
            elif ah == ARROW_POSITION_END:
                if arrow.GetXOffset() and not self._ignoreArrowOffsets:
                    self.DrawArrow(dc, arrow, arrow.GetXOffset(), True)
                else:
                    self.DrawArrow(dc, arrow, endArrowPos, False)
                    endArrowPos += arrow.GetSize() + arrow.GetSpacing()
            elif ah == ARROW_POSITION_MIDDLE:
                arrow.SetXOffset(middleArrowPos)
                if arrow.GetXOffset() and not self._ignoreArrowOffsets:
                    self.DrawArrow(dc, arrow, arrow.GetXOffset(), True)
                else:
                    self.DrawArrow(dc, arrow, middleArrowPos, False)
                    middleArrowPos += arrow.GetSize() + arrow.GetSpacing()

    def DrawArrow(self, dc, arrow, XOffset, proportionalOffset):
        """Draw the given arrowhead (or annotation)."""
        first_line_point = self._lineControlPoints[0]
        second_line_point = self._lineControlPoints[1]

        last_line_point = self._lineControlPoints[-1]
        second_last_line_point = self._lineControlPoints[-2]

        # Position of start point of line, at the end of which we draw the arrow
        startPositionX, startPositionY = 0.0, 0.0

        ap = arrow.GetPosition()
        if ap == ARROW_POSITION_START:
            # If we're using a proportional offset, calculate just where this
            # will be on the line.
            realOffset = XOffset
            if proportionalOffset:
                totalLength = math.sqrt((second_line_point[0] - first_line_point[0]) * (second_line_point[0] - first_line_point[0]) + (second_line_point[1] - first_line_point[1]) * (second_line_point[1] - first_line_point[1]))
                realOffset = XOffset * totalLength

            positionOnLineX, positionOnLineY = GetPointOnLine(second_line_point[0], second_line_point[1], first_line_point[0], first_line_point[1], realOffset)
            
            startPositionX = second_line_point[0]
            startPositionY = second_line_point[1]
        elif ap == ARROW_POSITION_END:
            # If we're using a proportional offset, calculate just where this
            # will be on the line.
            realOffset = XOffset
            if proportionalOffset:
                totalLength = math.sqrt((second_last_line_point[0] - last_line_point[0]) * (second_last_line_point[0] - last_line_point[0]) + (second_last_line_point[1] - last_line_point[1]) * (second_last_line_point[1] - last_line_point[1]));
                realOffset = XOffset * totalLength
            
            positionOnLineX, positionOnLineY = GetPointOnLine(second_last_line_point[0], second_last_line_point[1], last_line_point[0], last_line_point[1], realOffset)
            
            startPositionX = second_last_line_point[0]
            startPositionY = second_last_line_point[1]
        elif ap == ARROW_POSITION_MIDDLE:
            # Choose a point half way between the last and penultimate points
            x = (last_line_point[0] + second_last_line_point[0]) / 2.0
            y = (last_line_point[1] + second_last_line_point[1]) / 2.0

            # If we're using a proportional offset, calculate just where this
            # will be on the line.
            realOffset = XOffset
            if proportionalOffset:
                totalLength = math.sqrt((second_last_line_point[0] - x) * (second_last_line_point[0] - x) + (second_last_line_point[1] - y) * (second_last_line_point[1] - y));
                realOffset = XOffset * totalLength

            positionOnLineX, positionOnLineY = GetPointOnLine(second_last_line_point[0], second_last_line_point[1], x, y, realOffset)
            startPositionX = second_last_line_point[0]
            startPositionY = second_last_line_point[1]

        # Add yOffset to arrow, if any

        # The translation that the y offset may give
        deltaX = 0.0
        deltaY = 0.0
        if arrow.GetYOffset and not self._ignoreArrowOffsets:
            #                             |(x4, y4)
            #                             |d
            #                             |
            #   (x1, y1)--------------(x3, y3)------------------(x2, y2)
            #   x4 = x3 - d * math.sin(theta)
            #   y4 = y3 + d * math.cos(theta)
            #
            #   Where theta = math.tan(-1) of (y3-y1) / (x3-x1)
            x1 = startPositionX
            y1 = startPositionY
            x3 = float(positionOnLineX)
            y3 = float(positionOnLineY)
            d = -arrow.GetYOffset() # Negate so +offset is above line

            if x3 == x1:
                theta = math.pi / 2.0
            else:
                theta = math.atan((y3 - y1) / (x3 - x1))

            x4 = x3 - d * math.sin(theta)
            y4 = y3 + d * math.cos(theta)
            
            deltaX = x4 - positionOnLineX
            deltaY = y4 - positionOnLineY

        at = arrow._GetType()
        if at == ARROW_ARROW:
            arrowLength = arrow.GetSize()
            arrowWidth = arrowLength / 3.0

            tip_x, tip_y, side1_x, side1_y, side2_x, side2_y = GetArrowPoints(startPositionX + deltaX, startPositionY + deltaY, positionOnLineX + deltaX, positionOnLineY + deltaY, arrowLength, arrowWidth)

            points = [[tip_x, tip_y],
                    [side1_x, side1_y],
                    [side2_x, side2_y],
                    [tip_x, tip_y]]

            dc.SetPen(self._pen)
            dc.SetBrush(self._brush)
            dc.DrawPolygon(points)
        elif at in [ARROW_HOLLOW_CIRCLE, ARROW_FILLED_CIRCLE]:
            # Find point on line of centre of circle, which is a radius away
            # from the end position
            diameter = arrow.GetSize()
            x, y = GetPointOnLine(startPositionX + deltaX, startPositionY + deltaY,
                               positionOnLineX + deltaX, positionOnLineY + deltaY,
                               diameter / 2.0)
            x1 = x - diameter / 2.0
            y1 = y - diameter / 2.0
            dc.SetPen(self._pen)
            if arrow._GetType() == ARROW_HOLLOW_CIRCLE:
                dc.SetBrush(self.GetBackgroundBrush())
            else:
                dc.SetBrush(self._brush)

            dc.DrawEllipse(x1, y1, diameter, diameter)
        elif at == ARROW_SINGLE_OBLIQUE:
            pass
        elif at == ARROW_METAFILE:
            if arrow.GetMetaFile():
                # Find point on line of centre of object, which is a half-width away
                # from the end position
                #
                #                 width
                #  <-- start pos  <-----><-- positionOnLineX
                #                 _____
                #  --------------|  x  | <-- e.g. rectangular arrowhead
                #                 -----
                #
                x, y = GetPointOnLine(startPositionX, startPositionY,
                                   positionOnLineX, positionOnLineY,
                                   arrow.GetMetaFile()._width / 2.0)
                # Calculate theta for rotating the metafile.
                #
                # |
                # |     o(x2, y2)   'o' represents the arrowhead.
                # |    /
                # |   /
                # |  /theta
                # | /(x1, y1)
                # |______________________
                #
                theta = 0.0
                x1 = startPositionX
                y1 = startPositionY
                x2 = float(positionOnLineX)
                y2 = float(positionOnLineY)

                if x1 == x2 and y1 == y2:
                    theta = 0.0
                elif x1 == x2 and y1 > y2:
                    theta = 3.0 * math.pi / 2.0
                elif x1 == x2 and y2 > y1:
                    theta = math.pi / 2.0
                elif x2 > x1 and y2 >= y1:
                    theta = math.atan((y2 - y1) / (x2 - x1))
                elif x2 < x1:
                    theta = math.pi + math.atan((y2 - y1) / (x2 - x1))
                elif x2 > x1 and y2 < y1:
                    theta = 2 * math.pi + math.atan((y2 - y1) / (x2 - x1))
                else:
                    raise "Unknown arrowhead rotation case"

                # Rotate about the centre of the object, then place
                # the object on the line.
                if arrow.GetMetaFile().GetRotateable():
                    arrow.GetMetaFile().Rotate(0.0, 0.0, theta)

                if self._erasing:
                    # If erasing, just draw a rectangle
                    minX, minY, maxX, maxY = arrow.GetMetaFile().GetBounds()
                    # Make erasing rectangle slightly bigger or you get droppings
                    extraPixels = 4
                    dc.DrawRectangle(deltaX + x + minX - extraPixels / 2.0, deltaY + y + minY - extraPixels / 2.0, maxX - minX + extraPixels, maxY - minY + extraPixels)
                else:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -