B
    ]t\7<                 @   s   d Z ddlZddlZddlmZ G dd deZdd Zdd	 Z	d
d Z
dd Zd.ddZG dd deZd/ddZd0ddZd1ddZdd Zdd Zd2d!d"Zd#d$ Zd%d& Zd3d(d)Zd*d+ Zd,d- ZdS )4zO
A module providing some utility functions regarding bezier path manipulation.
    N)Pathc               @   s   e Zd ZdS )NonIntersectingPathExceptionN)__name__
__module____qualname__ r   r   0lib/python3.7/site-packages/matplotlib/bezier.pyr      s   r   c                s   ||  ||  }|| ||  }	||  }
}||  }}|
| ||   t  dk r^td||  }}| |
 }} fdd||||gD \}}}}|| ||	  }|| ||	  }||fS )z return a intersecting point between a line through (cx1, cy1)
    and having angle t1 and a line through (cx2, cy2) and angle t2.
    g-q=zcGiven lines do not intersect. Please verify that the angles are not equal or differ by 180 degrees.c                s   g | ]}|  qS r   r   ).0k)ad_bcr   r   
<listcomp>)   s    z$get_intersection.<locals>.<listcomp>)npabs
ValueError)Zcx1Zcy1cos_t1sin_t1Zcx2Zcy2cos_t2sin_t2Z	line1_rhsZ	line2_rhsabcdZa_Zb_Zc_Zd_xyr   )r   r   get_intersection   s    	"r   c             C   sl   |dkr| || |fS ||  }}| | }}|| |  || |  }	}
|| |  || |  }}|	|
||fS )z
    For a line passing through (*cx*, *cy*) and having a angle *t*, return
    locations of the two points located along its perpendicular line at the
    distance of *length*.
    g        r   )cxcycos_tsin_tlengthr   r   r   r   x1y1Zx2Zy2r   r   r   get_normal_points1   s    r"   c             C   s(   | d d d|  | dd  |  }|S )N   r   )betatZ	next_betar   r   r   _de_casteljau1J   s    $r'   c             C   s`   t | } | g}x&t| |} ||  t| dkrP qW dd |D }dd t|D }||fS )zsplit a bezier segment defined by its controlpoints *beta*
    into two separate segment divided at *t* and return their control points.

    r$   c             S   s   g | ]}|d  qS )r   r   )r	   r%   r   r   r   r   [   s    z&split_de_casteljau.<locals>.<listcomp>c             S   s   g | ]}|d  qS )r#   r   )r	   r%   r   r   r   r   \   s    )r   asarrayr'   appendlenreversed)r%   r&   Z	beta_listZ	left_betaZ
right_betar   r   r   split_de_casteljauO   s    


r,                 ?{Gz?c             C   s   | |}| |}||}||}||kr8||kr8t dxrt|d |d  |d |d  |k rj||fS d||  }	| |	}
||
}||A r|	}|
}|}q:|	}|
}|}q:W dS )a%   Find a parameter t0 and t1 of the given bezier path which
    bounds the intersecting points with a provided closed
    path(*inside_closedpath*). Search starts from *t0* and *t1* and it
    uses a simple bisecting algorithm therefore one of the end point
    must be inside the path while the orther doesn't. The search stop
    when |t0-t1| gets smaller than the given tolerence.
    value for

    - bezier_point_at_t : a function which returns x, y coordinates at *t*

    - inside_closedpath : return True if the point is inside the path

    z3Both points are on the same side of the closed pathr   r$   g      ?N)r   r   Zhypot)bezier_point_at_tinside_closedpatht0t1	tolerencestartendZstart_insideZ
end_insideZmiddle_tZmiddleZmiddle_insider   r   r   *find_bezier_t_intersecting_with_closedpathb   s(    (r7   c               @   sP   e Zd ZdZeddgedddgeddddgdZdd Zdd	 Zd
S )BezierSegmentz:
    A simple class of a 2-dimensional bezier segment
    g      ?g       @g      @)r$         c             C   sJ   t |}t|| _tj|d  }t|j\}}|| | _|| | _	dS )z
        *control_points* : location of contol points. It needs have a
         shpae of n * 2, where n is the order of the bezier line. 1<=
         n <= 3 is supported.
        r$   N)
r*   r   Zarange_ordersr8   _binom_coeffr(   T_px_py)selfZcontrol_pointsZ_oZ_coeffZxxZyyr   r   r   __init__   s    
zBezierSegment.__init__c             C   sF   d| | j  ddd || j   }t|| j}t|| j}||fS )zevaluate a point at tr$   Nr#   )r;   r   dotr>   r?   )r@   r&   ZttZ_xZ_yr   r   r   
point_at_t   s    "zBezierSegment.point_at_tN)	r   r   r   __doc__r   Zarrayr<   rA   rC   r   r   r   r   r8      s   r8   c       	      C   s>   t | }|j}t|||d\}}t| || d \}}||fS )z
    bezier : control points of the bezier segment
    inside_closedpath : a function which returns true if the point is inside
                        the path
    )r4   g       @)r8   rC   r7   r,   )	Zbezierr1   r4   Zbzr0   r2   r3   Z_leftZ_rightr   r   r   )split_bezier_intersecting_with_closedpath   s    
rE   c                s0   |\ fdd}t || |||d dS )z
    Find a radius r (centered at *xy*) between *rmin* and *rmax* at
    which it intersect with the path.

    inside_closedpath : function
    cx, cy : center
    cos_t, sin_t : cosine and sine for the angle
    rmin, rmax :
    c                s    |   |   fS )Nr   )r)r   r   r   r   r   r   _f   s    z,find_r_to_boundary_of_closedpath.<locals>._f)r2   r3   r4   N)r7   )r1   xyr   r   ZrminZrmaxr4   rG   r   )r   r   r   r   r    find_r_to_boundary_of_closedpath   s
    rI   Fc             C   s  |   }t|\}}||dd }|}tj}	d}
d}xZ|D ]J\}}|}
|t|d 7 }||dd |kr|	|dd |g}P |}q<W td|d}t|||\}}t|dkrtj	g}tj
tj	g}nft|dkrtjtjg}tj
tjtjg}n<t|d	kr,tjtjtjg}tj
tjtjtjg}ntd
|dd }|dd }| jdkrt|	| jd| |g}t|	|| j|d g}n\t|	| jd|
 |g|	| jd|
 |g}t|	|| j|d g|	|| j|d g}|r|dkr|| }}||fS )zW divide a path into two segment at the point where inside(x, y)
    becomes False.
    Nr   r$   r9   z*The path does not intersect with the patch)r#   r9   r:      zThis should never be reachedF)Ziter_segmentsnextr   concatenater*   r   ZreshaperE   r   LINETOMOVETOZCURVE3ZCURVE4AssertionErrorcodesvertices)pathZinsider4   Zreorder_inoutZ	path_iterZ
ctl_pointsZcommandZbegin_insideZctl_points_oldconcatZioldiZbezier_pathZbpleftrightZ
codes_leftZcodes_rightZ
verts_leftZverts_rightZpath_inZpath_outr   r   r   split_path_inout   sP    

rX   c                s   |d  fdd}|S )Nr9   c                s$   | \}}|  d | d  k S )Nr9   r   )rH   r   r   )r   r   r2r   r   rG   #  s    zinside_circle.<locals>._fr   )r   r   rF   rG   r   )r   r   rY   r   inside_circle   s    rZ   c             C   sB   ||  ||  }}|| ||  d }|dkr2dS || || fS )Ng      ?r   )g        g        r   )Zx0Zy0r    r!   ZdxZdyr   r   r   r   get_cos_sin+  s
    r[   h㈵>c             C   sR   t | |}t ||}t || }||k r2dS t |t j |k rJdS dS dS )z returns
       * 1 if two lines are parralel in same direction
       * -1 if two lines are parralel in opposite direction
       * 0 otherwise
    r$   r#   FN)r   Zarctan2r   Zpi)Zdx1Zdy1Zdx2Zdy2r4   Ztheta1Ztheta2Zdthetar   r   r   check_if_parallel4  s    r]   c          	   C   sn  | d \}}| d \}}| d \}}t || || || || }|dkrrtd t||||\}	}
|	|
 }}n$t||||\}	}
t||||\}}t|||	|
|\}}}}t|||||\}}}}|dkrd||  d||   }}d||  d||   }}n4t|||	|
||||\}}t|||	|
||||\}}||f||f||fg}||f||f||fg}||fS )z
    Given the quadratic bezier control points *bezier2*, returns
    control points of quadratic bezier lines roughly parallel to given
    one separated by *width*.
    r   r$   r9   r#   z8Lines do not intersect. A straight line is used instead.g      ?)r]   warningswarnr[   r"   r   )bezier2widthc1xc1ycmxcmyc2xc2yZparallel_testr   r   r   r   c1x_leftc1y_left	c1x_right	c1y_rightZc2x_leftZc2y_leftZ	c2x_rightZ	c2y_rightZcmx_leftZcmy_leftZ	cmx_rightZ	cmy_right	path_left
path_rightr   r   r   get_parallelsE  s<    


rn   c             C   s>   dd| | |   }dd| ||   }| |f||f||fgS )z Find control points of the bezier line through c1, mm, c2. We
    simply assume that c1, mm, c2 which have parametric value 0, 0.5, and 1.
    g      ?rK   r   )rb   rc   ZmmxZmmyrf   rg   rd   re   r   r   r   find_control_points  s    ro         ?c       %      C   s(  | d \}}| d \}}| d \}	}
t ||||\}}t |||	|
\}}t|||||| \}}}}t|	|
|||| \}}}}|| d || d  }}||	 d ||
 d  }}|| d || d  }}t ||||\}}t|||||| \}} }!}"t|||| ||}#t|||!|"||}$|#|$fS )z
    Being similar to get_parallels, returns control points of two quadrativ
    bezier lines having a width roughly parallel to given one separated by
    *width*.
    r   r$   r9   g      ?)r[   r"   ro   )%r`   ra   Zw1ZwmZw2rb   rc   rd   re   Zc3xZc3yr   r   r   r   rh   ri   rj   rk   Zc3x_leftZc3y_leftZ	c3x_rightZ	c3y_rightZc12xZc12yZc23xZc23yZc123xZc123yZcos_t123Zsin_t123Z
c123x_leftZ
c123y_leftZc123x_rightZc123y_rightrl   rm   r   r   r   make_wedged_bezier2  s&    rq   c             C   sP   | j }|dkrHt| jjdd d}|tj tj|d< t| j|S | S dS )z$
    fill in the codes if None.
    Nr$   rU   r   )	rQ   r   emptyrR   shapeZfillr   rN   rO   )pr   r   r   r   make_path_regular  s    
ru   c             C   sP   g }g }x,| D ]$}t |}||j ||j qW tt|t|}|S )z7
    concatenate list of paths into a single path.
    )ru   r)   rR   rQ   r   r   rM   )pathsrR   rQ   rt   _pathr   r   r   concatenate_paths  s    

rx   )r-   r.   r/   )r/   )r-   r.   r/   )r/   F)r\   )r.   rp   r-   )rD   r^   Znumpyr   Zmatplotlib.pathr   r   r   r   r"   r'   r,   r7   objectr8   rE   rI   rX   rZ   r[   r]   rn   ro   rq   ru   rx   r   r   r   r   <module>   s*    
/#


>	
J
3