@@ -2841,6 +2841,18 @@ def connect(self, posA, posB):
28412841 {"AvailableConnectorstyles" : _pprint_styles (_style_list )}
28422842
28432843
2844+ def _point_along_a_line (x0 , y0 , x1 , y1 , d ):
2845+ """
2846+ find a point along a line connecting (x0, y0) -- (x1, y1) whose
2847+ distance from (x0, y0) is d.
2848+ """
2849+ dx , dy = x0 - x1 , y0 - y1
2850+ ff = d / (dx * dx + dy * dy )** .5
2851+ x2 , y2 = x0 - ff * dx , y0 - ff * dy
2852+
2853+ return x2 , y2
2854+
2855+
28442856class ArrowStyle (_Style ):
28452857 """
28462858 :class:`ArrowStyle` is a container class which defines several
@@ -3460,35 +3472,57 @@ def transmute(self, path, mutation_size, linewidth):
34603472 head_length = self .head_length * mutation_size
34613473 in_f = inside_circle (x2 , y2 , head_length )
34623474 arrow_path = [(x0 , y0 ), (x1 , y1 ), (x2 , y2 )]
3463- arrow_out , arrow_in = \
3464- split_bezier_intersecting_with_closedpath (arrow_path ,
3465- in_f ,
3466- tolerence = 0.01 )
3475+
3476+ from bezier import NonIntersectingPathException
3477+
3478+ try :
3479+ arrow_out , arrow_in = \
3480+ split_bezier_intersecting_with_closedpath (arrow_path ,
3481+ in_f ,
3482+ tolerence = 0.01 )
3483+ except NonIntersectingPathException :
3484+ # if this happens, make a straight line of the head_length long.
3485+ x0 , y0 = _point_along_a_line (x2 , y2 , x1 , y1 , head_length )
3486+ x1n , y1n = 0.5 * (x0 + x2 ), 0.5 * (y0 + y2 )
3487+ arrow_in = [(x0 , y0 ), (x1n , y1n ), (x2 , y2 )]
3488+ arrow_out = None
34673489
34683490 # head
34693491 head_width = self .head_width * mutation_size
3470- head_l , head_r = make_wedged_bezier2 (arrow_in , head_width / 2. ,
3471- wm = .5 )
3492+ head_left , head_right = \
3493+ make_wedged_bezier2 (arrow_in , head_width / 2. ,
3494+ wm = .5 )
3495+
34723496
34733497 # tail
3474- tail_width = self .tail_width * mutation_size
3475- tail_left , tail_right = get_parallels (arrow_out , tail_width / 2. )
3498+ if arrow_out is not None :
3499+ tail_width = self .tail_width * mutation_size
3500+ tail_left , tail_right = get_parallels (arrow_out , tail_width / 2. )
3501+
3502+ #head_right, head_left = head_r, head_l
3503+ patch_path = [(Path .MOVETO , tail_right [0 ]),
3504+ (Path .CURVE3 , tail_right [1 ]),
3505+ (Path .CURVE3 , tail_right [2 ]),
3506+ (Path .LINETO , head_right [0 ]),
3507+ (Path .CURVE3 , head_right [1 ]),
3508+ (Path .CURVE3 , head_right [2 ]),
3509+ (Path .CURVE3 , head_left [1 ]),
3510+ (Path .CURVE3 , head_left [0 ]),
3511+ (Path .LINETO , tail_left [2 ]),
3512+ (Path .CURVE3 , tail_left [1 ]),
3513+ (Path .CURVE3 , tail_left [0 ]),
3514+ (Path .LINETO , tail_right [0 ]),
3515+ (Path .CLOSEPOLY , tail_right [0 ]),
3516+ ]
3517+ else :
3518+ patch_path = [(Path .MOVETO , head_right [0 ]),
3519+ (Path .CURVE3 , head_right [1 ]),
3520+ (Path .CURVE3 , head_right [2 ]),
3521+ (Path .CURVE3 , head_left [1 ]),
3522+ (Path .CURVE3 , head_left [0 ]),
3523+ (Path .CLOSEPOLY , head_left [0 ]),
3524+ ]
34763525
3477- head_right , head_left = head_r , head_l
3478- patch_path = [(Path .MOVETO , tail_right [0 ]),
3479- (Path .CURVE3 , tail_right [1 ]),
3480- (Path .CURVE3 , tail_right [2 ]),
3481- (Path .LINETO , head_right [0 ]),
3482- (Path .CURVE3 , head_right [1 ]),
3483- (Path .CURVE3 , head_right [2 ]),
3484- (Path .CURVE3 , head_left [1 ]),
3485- (Path .CURVE3 , head_left [0 ]),
3486- (Path .LINETO , tail_left [2 ]),
3487- (Path .CURVE3 , tail_left [1 ]),
3488- (Path .CURVE3 , tail_left [0 ]),
3489- (Path .LINETO , tail_right [0 ]),
3490- (Path .CLOSEPOLY , tail_right [0 ]),
3491- ]
34923526 path = Path ([p for c , p in patch_path ], [c for c , p in patch_path ])
34933527
34943528 return path , True
@@ -3536,12 +3570,10 @@ def transmute(self, path, mutation_size, linewidth):
35363570 in_f ,
35373571 tolerence = 0.01 )
35383572 except NonIntersectingPathException :
3539- # if this happens, make a straight line of the head_length
3540- # long.
3541- dx , dy = x2 - x1 , y2 - y1
3542- ff = head_length / (dx * dx + dy * dy ) ** .5
3543- x0 , y0 = x2 - ff * dx , y2 - ff * dy
3544- arrow_path = [(x0 , y0 ), (x1 , y1 ), (x2 , y2 )]
3573+ # if this happens, make a straight line of the head_length long.
3574+ x0 , y0 = _point_along_a_line (x2 , y2 , x1 , y1 , head_length )
3575+ x1n , y1n = 0.5 * (x0 + x2 ), 0.5 * (y0 + y2 )
3576+ arrow_path = [(x0 , y0 ), (x1n , y1n ), (x2 , y2 )]
35453577 path_head = arrow_path
35463578 else :
35473579 path_head = path_in
0 commit comments