示例#1
0
def make_path(d, style):
    items = []
    for c in d.split():
        if c.upper() in codemap:
            items.append(c)
        else:
            x, y = (float(v) for v in c.split(","))
            items.append((x, y))
    codes = []
    vertices = []
    i = 0
    lx, ly = 0, 0
    last_code = "M"
    while i < len(items):
        code = items[i]
        if not isinstance(code, str):
            code = last_code
        else:
            i += 1
        ucode = code.upper()
        if code.isupper():
            relative = False
        else:
            relative = True
        if ucode in ("M", "L"):
            x, y = items[i]
            i += 1
            if relative:
                x += lx
                y += ly
            codes.append(codemap[ucode])
            vertices.append((x, y))
            lx, ly = x, y
        if ucode == "C":
            if not relative:
                points = items[i:i + 3]
            else:
                points = [(_x + lx, _y + ly) for _x, _y in items[i:i + 3]]
            codes.extend([codemap[ucode]] * 3)
            vertices.extend(points)
            lx, ly = points[-1]
            i += 3
        if ucode == "Z":
            break
        last_code = code

    codes[0] = Path.MOVETO
    patch = PathPatch(Path(vertices, codes))
    patch.set_linewidth(get_number(style.get("stroke-width", "1px")))
    fill = style.get("fill", "none")
    if fill == "none":
        patch.set_fill(None)
    else:
        patch.set_facecolor(fill)
    edge = style.get("stroke", "none")
    patch.set_edgecolor(edge)

    return patch
示例#2
0
文件: svg_path.py 项目: hejibo/scpy2
def make_path(d, style):
    items = []
    for c in d.split():
        if c.upper() in codemap:
            items.append(c)
        else:
            x, y = (float(v) for v in c.split(","))
            items.append((x, y))
    codes = []
    vertices = []            
    i = 0
    lx, ly = 0, 0
    last_code = "M"
    while i < len(items):
        code = items[i]
        if not isinstance(code, str):
            code = last_code
        else:
            i += 1
        ucode = code.upper()
        if code.isupper():
            relative = False
        else:
            relative = True
        if ucode in ("M", "L"):
            x, y = items[i]
            i += 1
            if relative:
                x += lx
                y += ly
            codes.append(codemap[ucode])
            vertices.append((x, y))
            lx, ly = x, y
        if ucode == "C":
            if not relative:
                points = items[i:i+3]
            else:
                points = [(_x + lx, _y + ly) for _x, _y in items[i:i+3]]
            codes.extend([codemap[ucode]]*3)
            vertices.extend(points)
            lx, ly = points[-1]
            i += 3
        if ucode == "Z":
            break
        last_code = code
        
    codes[0] = Path.MOVETO
    patch = PathPatch( Path(vertices, codes) )
    patch.set_linewidth( get_number(style.get("stroke-width", "1px") ) )
    fill =  style.get("fill", "none")
    if fill == "none":
        patch.set_fill( None )
    else:
        patch.set_facecolor( fill )
    edge = style.get("stroke", "none")
    patch.set_edgecolor(edge)

    return patch
示例#3
0
    def _render_on_subplot(self, subplot):
        """
        Render this Bezier path in a subplot.  This is the key function that
        defines how this Bezier path graphics primitive is rendered in matplotlib's
        library.

        TESTS::

            sage: bezier_path([[(0,1),(.5,0),(1,1)]])
            Graphics object consisting of 1 graphics primitive

        ::

            sage: bezier_path([[(0,1),(.5,0),(1,1),(-3,5)]])
            Graphics object consisting of 1 graphics primitive
        """
        from matplotlib.patches import PathPatch
        from matplotlib.path import Path
        from sage.plot.misc import get_matplotlib_linestyle

        options = dict(self.options())

        del options['alpha']
        del options['thickness']
        del options['rgbcolor']
        del options['zorder']
        del options['fill']
        del options['linestyle']

        bpath = Path(self.vertices, self.codes)
        bpatch = PathPatch(bpath, **options)
        options = self.options()
        bpatch.set_linewidth(float(options['thickness']))
        bpatch.set_fill(options['fill'])
        bpatch.set_zorder(options['zorder'])
        a = float(options['alpha'])
        bpatch.set_alpha(a)
        c = to_mpl_color(options['rgbcolor'])
        bpatch.set_edgecolor(c)
        bpatch.set_facecolor(c)
        bpatch.set_linestyle(
            get_matplotlib_linestyle(options['linestyle'], return_type='long'))
        subplot.add_patch(bpatch)
示例#4
0
    def _render_on_subplot(self, subplot):
        """
        Render this Bezier path in a subplot.  This is the key function that
        defines how this Bezier path graphics primitive is rendered in matplotlib's
        library.

        TESTS::

            sage: bezier_path([[(0,1),(.5,0),(1,1)]])
            Graphics object consisting of 1 graphics primitive

        ::

            sage: bezier_path([[(0,1),(.5,0),(1,1),(-3,5)]])
            Graphics object consisting of 1 graphics primitive
        """
        from matplotlib.patches import PathPatch
        from matplotlib.path import Path
        from sage.plot.misc import get_matplotlib_linestyle

        options = dict(self.options())

        del options['alpha']
        del options['thickness']
        del options['rgbcolor']
        del options['zorder']
        del options['fill']
        del options['linestyle']

        bpath = Path(self.vertices, self.codes)
        bpatch = PathPatch(bpath, **options)
        options = self.options()
        bpatch.set_linewidth(float(options['thickness']))
        bpatch.set_fill(options['fill'])
        bpatch.set_zorder(options['zorder'])
        a = float(options['alpha'])
        bpatch.set_alpha(a)
        c = to_mpl_color(options['rgbcolor'])
        bpatch.set_edgecolor(c)
        bpatch.set_facecolor(c)
        bpatch.set_linestyle(get_matplotlib_linestyle(options['linestyle'], return_type='long'))
        subplot.add_patch(bpatch)
示例#5
0
class VerticalMarker(QObject):
    """
    An interactive marker displayed as a vertical line.
    """

    x_moved = Signal(float)

    def __init__(self,
                 canvas,
                 color,
                 x,
                 y0=None,
                 y1=None,
                 line_width=1.0,
                 picker_width=5,
                 line_style='-',
                 move_cursor=None,
                 axis=None):
        """
        Init the marker.
        :param canvas: A MPL canvas.
        :param color: An MPL colour value
        :param x: The x coordinate (data) of the marker.
        :param y0: The y coordinate (data) of the bottom end of the marker. Default is None which means dynamically
            set it to the current lowest y value displayed.
        :param y1: The y coordinate (data) of the top end of the marker. Default is None which means dynamically
            set it to the current highest y value displayed.
        :param line_width: The line width (pixels).
        :param picker_width: The picker sensitivity (pixels).
        :param line_style: An MPL line style value.
        """
        super(VerticalMarker, self).__init__()
        self.canvas = canvas
        if axis is None:
            self.axis = canvas.figure.get_axes()[0]
        else:
            self.axis = axis
        self.x = x
        self.y0 = y0
        self.y1 = y1
        y0, y1 = self._get_y0_y1()
        path = Path([(x, y0), (x, y1)], [Path.MOVETO, Path.LINETO])
        self.patch = PathPatch(path,
                               facecolor='None',
                               edgecolor=color,
                               picker=picker_width,
                               linewidth=line_width,
                               linestyle=line_style,
                               animated=True)
        self.axis.add_patch(self.patch)
        self.axis.interactive_markers.append(self.patch)
        self.is_moving = False
        self.move_cursor = move_cursor

    def _get_y0_y1(self):
        """
        Calculate the current y coordinates of the line ends.
        :return: Tuple y0, y1.
        """
        if self.y0 is None or self.y1 is None:
            y0, y1 = self.axis.get_ylim()
        if self.y0 is not None:
            y0 = self.y0
        if self.y1 is not None:
            y1 = self.y1
        return y0, y1

    def remove(self):
        """
        Remove this marker from the canvas.
        """
        self.patch.remove()

    def redraw(self):
        """
        Redraw this marker.
        """
        y0, y1 = self._get_y0_y1()
        vertices = self.patch.get_path().vertices
        vertices[0] = self.x, y0
        vertices[1] = self.x, y1
        self.axis.draw_artist(self.patch)

    def set_visible(self, visible):
        self.patch.set_visible(visible)

    def set_color(self, color):
        """
        Set the colour of the marker
        :param color: The color to set the marker to.
        """
        self.patch.set_edgecolor(color)

    def get_position(self):
        """
        Get the x coordinate in axes coords.
        :return: x in axes coords
        """
        return self.x

    def set_position(self, x):
        """
        Set the x position of the marker.
        :param x: An x axis coordinate.
        """
        self.x = x
        self.x_moved.emit(x)

    def get_x_in_pixels(self):
        """
        Get the x coordinate in screen pixels.
        :return: x in pixels
        """
        x_pixels, _ = self.patch.get_transform().transform((self.x, 0))
        return x_pixels

    def is_above(self, x, y):
        """
        Check if a mouse positioned at (x, y) is over this marker.
        :param x: An x mouse coordinate.
        :param y: An y mouse coordinate.
        :return: True or False.
        """
        x_pixels, _ = self.patch.get_transform().transform((x, y))

        if self.y0 is not None and y < self.y0:
            return False
        if self.y1 is not None and y > self.y1:
            return False
        return abs(self.get_x_in_pixels() - x_pixels) < MARKER_SENSITIVITY

    def mouse_move_start(self, x, y):
        """
        Start moving this marker if (x, y) is above it. Ignore otherwise.
        :param x: An x mouse coordinate.
        :param y: An y mouse coordinate.
        """
        self.is_moving = self.is_above(x, y)

    def mouse_move_stop(self):
        """
        Stop moving.
        """
        self.is_moving = False

    def mouse_move(self, x, y=None):
        """
        Move this marker to a new position if movement had been started earlier by a call to mouse_move_start(x, y)
        :param x: An x mouse coordinate.
        :param y: An y mouse coordinate.
        :return: True if moved or False if stayed at the old position.
        """
        if self.is_moving and x is not None:
            self.set_position(x)
            return True
        return False

    def is_marker_moving(self):
        """
        Returns true if the marker is being moved
        :return: True if the marker is being moved.
        """
        return self.is_moving

    def get_cursor_at_y(self, y):
        """
        Get an override cursor for an y coordinate given that the x == self.x
        :param y: A y coordinate.
        :return: QCursor or None.
        """
        return self.move_cursor if self.move_cursor is not None else QCursor(
            Qt.SizeHorCursor)

    def override_cursor(self, x, y):
        """
        Get the override cursor for mouse position (x, y)
        :param x: An x mouse coordinate.
        :param y: An y mouse coordinate.
        :return: QCursor or None.
        """
        if self.y0 is not None and y < self.y0:
            return None
        if self.y1 is not None and y > self.y1:
            return None
        if self.is_moving or self.is_above(x, y):
            return self.get_cursor_at_y(y)
        return None

    def set_move_cursor(self, cursor, x_pos, y_pos):
        """Set the style of the cursor to use when the marker is moving"""
        if cursor is not None:
            cursor = QCursor(cursor)
        self.move_cursor = cursor
        self.override_cursor(x_pos, y_pos)
示例#6
0
class HorizontalMarker(QObject):
    """
    An interactive marker displayed as a horizontal line.
    """

    y_moved = Signal(float)

    def __init__(self,
                 canvas,
                 color,
                 y,
                 x0=None,
                 x1=None,
                 line_width=1.0,
                 picker_width=5,
                 line_style='-',
                 move_cursor=None,
                 axis=None):
        """
        Init the marker.
        :param canvas: A MPL canvas.
        :param color: An MPL colour value
        :param y: The y coordinate (data) of the marker.
        :param x0: The x coordinate (data) of the left end of the marker. Default is None which means dynamically
            set it to the current maximum x value displayed.
        :param x1: The x coordinate (data) of the right end of the marker. Default is None which means dynamically
            set it to the current minimum x value displayed.
        :param line_width: The line width (pixels).
        :param picker_width: The picker sensitivity (pixels).
        :param line_style: An MPL line style value.
        """
        super(HorizontalMarker, self).__init__()
        self.canvas = canvas
        if axis is None:
            self.axis = canvas.figure.get_axes()[0]
        else:
            self.axis = axis
        self.y = y
        self.x0 = x0
        self.x1 = x1
        x0, x1 = self._get_x0_x1()
        path = Path([(x0, y), (x1, y)], [Path.MOVETO, Path.LINETO])
        self.patch = PathPatch(path,
                               facecolor='None',
                               edgecolor=color,
                               picker=picker_width,
                               linewidth=line_width,
                               linestyle=line_style,
                               animated=True)
        self.axis.add_patch(self.patch)
        self.axis.interactive_markers.append(self.patch)
        self.is_moving = False
        self.move_cursor = move_cursor

    def _get_x0_x1(self):
        """
        Calculate the current x coordinates of the line ends.
        :return: Tuple x0, x1.
        """
        if self.x0 is None or self.x1 is None:
            x0, x1 = self.axis.get_xlim()
        if self.x0 is not None:
            x0 = self.x0
        if self.x1 is not None:
            x1 = self.x1
        return x0, x1

    def remove(self):
        """
        Remove this marker from the canvas.
        """
        self.patch.remove()

    def redraw(self):
        """
        Redraw this marker.
        """
        x0, x1 = self._get_x0_x1()
        vertices = self.patch.get_path().vertices
        vertices[0] = x0, self.y
        vertices[1] = x1, self.y
        self.axis.draw_artist(self.patch)

    def set_visible(self, visible):
        self.patch.set_visible(visible)

    def set_color(self, color):
        """
        Set the colour of the marker
        :param color: The color to set the marker to.
        """
        self.patch.set_edgecolor(color)

    def get_position(self):
        """
        Get the y coordinate in axes coords.
        :return: y in axes coords
        """
        return self.y

    def set_position(self, y):
        """
        Set the y position of the marker.
        :param y: An y axis coordinate.
        """
        self.y = y
        self.y_moved.emit(y)

    def get_y_in_pixels(self):
        """
        Returns the y coordinate in screen pixels.
        :return: y in pixels
        """
        _, y_pixels = self.patch.get_transform().transform((0, self.y))
        return y_pixels

    def is_above(self, x, y):
        """
        Check if a mouse positioned at (x, y) is over this marker.
        :param x: An x mouse coordinate.
        :param y: An y mouse coordinate.
        :return: True or False.
        """
        _, y_pixels = self.patch.get_transform().transform((x, y))

        if self.x0 is not None and x < self.x0:
            return False
        if self.x1 is not None and x > self.x1:
            return False
        return abs(self.get_y_in_pixels() - y_pixels) < MARKER_SENSITIVITY

    def mouse_move_start(self, x, y):
        """
        Start moving this marker if (x, y) is above it. Ignore otherwise.
        :param x: An x mouse coordinate.
        :param y: An y mouse coordinate.
        :param pixels: True if the coordinates are already in pixels.
        """
        self.is_moving = self.is_above(x, y)

    def mouse_move_stop(self):
        """
        Stop moving.
        """
        self.is_moving = False

    def mouse_move(self, x, y):
        """
        Move this marker to a new position if movement had been started earlier by a call to mouse_move_start(x, y)
        :param x: An x mouse coordinate.
        :param y: An y mouse coordinate.
        :return: True if moved or False if stayed at the old position.
        """
        if self.is_moving and y is not None and x is not None:
            self.set_position(y)
            return True
        return False

    def is_marker_moving(self):
        """
        Returns true if the marker is being moved
        :return: True if the marker is being moved.
        """
        return self.is_moving

    def override_cursor(self, x, y):
        """
        Get the override cursor for mouse position (x, y)
        :param x: An x mouse coordinate.
        :param y: An y mouse coordinate.
        :return: QCursor or None.
        """
        if self.x0 is not None and x < self.x0:
            return None
        if self.x1 is not None and x > self.x1:
            return None
        if self.is_moving or self.is_above(x, y):
            return self.move_cursor if self.move_cursor is not None else QCursor(
                Qt.SizeVerCursor)
        return None

    def set_move_cursor(self, cursor, x_pos, y_pos):
        """Set the style of the cursor to use when the marker is moving"""
        if cursor is not None:
            cursor = QCursor(cursor)
        self.move_cursor = cursor
        self.override_cursor(x_pos, y_pos)