Arrow with "simple" style is not robust. Code fix included. #1619

dhyams opened this Issue Dec 21, 2012 · 2 comments


None yet

2 participants


An arrow with the "simple" arrowstyle, if too short, throws a NonIntersectingPathException. The fix is below, which follows the same pattern as the "fancy" arrowstyle. I apologize for not submitting a github pull request, but I just don't have things set up properly to do it right now.

In (I'm working with MPL 1.1.1, so this is around line 3400), the transmute method for class Simple_ should be changed to (all added lines marked with ADDME).

   def transmute(self, path, mutation_size, linewidth):

        x0, y0, x1, y1, x2, y2 = self.ensure_quadratic_bezier(path)

        from bezier import NonIntersectingPathException # ADDME

        # divide the path into a head and a tail
        head_length  = self.head_length * mutation_size
        in_f = inside_circle(x2, y2, head_length)
        arrow_path = [(x0, y0), (x1, y1), (x2, y2)]
        try:  # ADDME
          arrow_out, arrow_in = \
        except NonIntersectingPathException: # ADDME
            # if this happens, make a straight line of the head_length long. # ADDME
            dx, dy = x2 - x1, y2 - y1 # ADDME
            ff = head_length/(dx*dx+dy*dy)**.5 # ADDME
            x0, y0 = x2 - ff*dx, y2 - ff*dy # ADDME
            arrow_in  = [(x0, y0), (x1, y1), (x2, y2)] # ADDME
            arrow_out = [(x0, y0), (x0, y0), (x0, y0)] # ADDME

        # head
        head_width = self.head_width * mutation_size
        head_l, head_r = make_wedged_bezier2(arrow_in, head_width/2.,

        # tail
        tail_width = self.tail_width * mutation_size
        tail_left, tail_right = get_parallels(arrow_out, tail_width/2.)

        head_right, head_left = head_r, head_l
        patch_path = [(Path.MOVETO, tail_right[0]),
                      (Path.CURVE3, tail_right[1]),
                      (Path.CURVE3, tail_right[2]),
                      (Path.LINETO, head_right[0]),
                      (Path.CURVE3, head_right[1]),
                      (Path.CURVE3, head_right[2]),
                      (Path.CURVE3, head_left[1]),
                      (Path.CURVE3, head_left[0]),
                      (Path.LINETO, tail_left[2]),
                      (Path.CURVE3, tail_left[1]),
                      (Path.CURVE3, tail_left[0]),
                      (Path.LINETO, tail_right[0]),
                      (Path.CLOSEPOLY, tail_right[0]),
        path = Path([p for c, p in patch_path], [c for c, p in patch_path])

        return path, True

This issue was addressed by #566

@dhyams dhyams closed this Feb 20, 2013
Matplotlib Developers member

Thanks for updating @dhyams .

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment