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

Closed
dhyams opened this Issue Dec 21, 2012 · 2 comments

Projects

None yet

2 participants

@dhyams

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 patches.py (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 = \
                   split_bezier_intersecting_with_closedpath(arrow_path,
                                                             in_f,
                                                             tolerence=0.01)
        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.,
                                             wm=.5)



        # 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
@dhyams

This issue was addressed by #566

@dhyams dhyams closed this Feb 20, 2013
@pelson
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