U
    Âmœd÷H  ã                   @   sà   d Z ddlmZ ddlZddlZddlZddlmZ ej	edd�dd„ ƒƒ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ƒZd.dd„Zd/dd„Zdd „ Zd!d"„ Zd0d$d%„Zd&d'„ Zd(d)„ Zd1d+d,„ZdS )2uP   
A module providing some utility functions regarding BÃ©zier path manipulation.
é    )Ú	lru_cacheN)Ú_apié€   )Úmaxsizec                 C   sF   || krdS t || | ƒ}t d|d ¡}t | d | | ¡ t¡S )Nr   é   )ÚminÚnpÚarangeÚprodZastypeÚint)ÚnÚkÚi© r   úJ/home/sam/Atlas/atlas_env/lib/python3.8/site-packages/matplotlib/bezier.pyÚ_comb   s
    r   c                   @   s   e Zd ZdS )ÚNonIntersectingPathExceptionN)Ú__name__Ú
__module__Ú__qualname__r   r   r   r   r      s   r   c                    s¾   ||  ||  }|| ||  }	||  }
}||  }}|
| ||  ‰ t ˆ ƒdk r\tdƒ‚||  }}| |
 }}‡ fdd„||||fD ƒ\}}}}|| ||	  }|| ||	  }||fS )zŽ
    Return the intersection between the line through (*cx1*, *cy1*) at angle
    *t1* and the line through (*cx2*, *cy2*) at 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   )Ú.0r   ©Zad_bcr   r   Ú
<listcomp>9   s     z$get_intersection.<locals>.<listcomp>)Ú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 an angle *t*, return
    locations of the two points located along its perpendicular line at the
    distance of *length*.
    ç        r   )ÚcxÚcyZcos_tZsin_tÚlengthr   r   r   r   Úx1Úy1Zx2Úy2r   r   r   Úget_normal_pointsA   s    r-   c                 C   s(   | d d… d|  | dd … |  }|S )Néÿÿÿÿr   r   )ÚbetaÚtZ	next_betar   r   r   Ú_de_casteljau1Z   s    $r1   c                 C   s\   t  | ¡} | g}t| |ƒ} | | ¡ t| ƒdkrq4qdd„ |D ƒ}dd„ t|ƒD ƒ}||fS )u•   
    Split a BÃ©zier segment defined by its control points *beta* into two
    separate segments divided at *t* and return their control points.
    r   c                 S   s   g | ]}|d  ‘qS )r   r   ©r   r/   r   r   r   r   k   s     z&split_de_casteljau.<locals>.<listcomp>c                 S   s   g | ]}|d  ‘qS )r.   r   r2   r   r   r   r   l   s     )r   Úasarrayr1   ÚappendÚlenÚreversed)r/   r0   Z	beta_listZ	left_betaZ
right_betar   r   r   Úsplit_de_casteljau_   s    


r7   r&   ç      ð?ç{®Gáz„?c                 C   s¨   | |ƒ}| |ƒ}||ƒ}||ƒ}||kr8||kr8t dƒ‚t |d |d  |d |d  ¡|k rh||fS d||  }	| |	ƒ}
||
ƒ}||A r–|	}|
}q8|	}|
}|}q8dS )uŒ  
    Find the intersection of the BÃ©zier curve with a closed path.

    The intersection point *t* is approximated by two parameters *t0*, *t1*
    such that *t0* <= *t* <= *t1*.

    Search starts from *t0* and *t1* and uses a simple bisecting algorithm
    therefore one of the end points must be inside the path while the other
    doesn't. The search stops when the distance of the points parametrized by
    *t0* and *t1* gets smaller than the given *tolerance*.

    Parameters
    ----------
    bezier_point_at_t : callable
        A function returning x, y coordinates of the BÃ©zier at parameter *t*.
        It must have the signature::

            bezier_point_at_t(t: float) -> tuple[float, float]

    inside_closedpath : callable
        A function returning True if a given point (x, y) is inside the
        closed path. It must have the signature::

            inside_closedpath(point: tuple[float, float]) -> bool

    t0, t1 : float
        Start parameters for the search.

    tolerance : float
        Maximal allowed distance between the final points.

    Returns
    -------
    t0, t1 : float
        The BÃ©zier path parameters.
    z3Both points are on the same side of the closed pathr   r   ç      à?N)r   r   Úhypot)Úbezier_point_at_tÚinside_closedpathÚt0Út1Ú	toleranceÚstartÚendZstart_insideZ
end_insideZmiddle_tÚmiddleZmiddle_insider   r   r   Ú*find_bezier_t_intersecting_with_closedpathq   s&    &ÿ(rD   c                   @   s`   e Zd ZdZdd„ Zdd„ Zdd„ Zedd	„ ƒZed
d„ ƒZ	edd„ ƒZ
edd„ ƒZdd„ ZdS )ÚBezierSegmentu—   
    A d-dimensional BÃ©zier segment.

    Parameters
    ----------
    control_points : (N, d) array
        Location of the *N* control points.
    c                    sV   t  |¡ˆ _ˆ jj\ˆ _ˆ _t  ˆ j¡ˆ _‡ fdd„tˆ jƒD ƒ}ˆ jj	| j	ˆ _
d S )Nc                    s:   g | ]2}t  ˆ jd  ¡t  |¡t  ˆ jd  | ¡  ‘qS )r   )ÚmathÚ	factorialÚ_N)r   r   ©Úselfr   r   r   Ã   s   þÿz*BezierSegment.__init__.<locals>.<listcomp>)r   r3   Ú_cpointsÚshaperH   Ú_dr	   Ú_ordersÚrangeÚTÚ_px)rJ   Úcontrol_pointsZcoeffr   rI   r   Ú__init__¿   s    
þzBezierSegment.__init__c                 C   s>   t  |¡}t j d| | jddd… ¡t j || j¡ | j S )u)  
        Evaluate the BÃ©zier curve at point(s) *t* in [0, 1].

        Parameters
        ----------
        t : (k,) array-like
            Points at which to evaluate the curve.

        Returns
        -------
        (k, d) array
            Value of the curve for each point in *t*.
        r   Nr.   )r   r3   ÚpowerÚouterrN   rQ   ©rJ   r0   r   r   r   Ú__call__È   s    
ÿÿzBezierSegment.__call__c                 C   s   t | |ƒƒS )zX
        Evaluate the curve at a single point, returning a tuple of *d* floats.
        )ÚtuplerV   r   r   r   Ú
point_at_tÚ   s    zBezierSegment.point_at_tc                 C   s   | j S )z The control points of the curve.)rK   rI   r   r   r   rR   à   s    zBezierSegment.control_pointsc                 C   s   | j S )zThe dimension of the curve.)rM   rI   r   r   r   Ú	dimensionå   s    zBezierSegment.dimensionc                 C   s
   | j d S )z@Degree of the polynomial. One less the number of control points.r   )rH   rI   r   r   r   Údegreeê   s    zBezierSegment.degreec                 C   s|   | j }|dkrt dt¡ | j}t |d ¡dd…df }t |d ¡ddd…f }d||  t||ƒ }t||ƒ| | S )uº  
        The polynomial coefficients of the BÃ©zier curve.

        .. warning:: Follows opposite convention from `numpy.polyval`.

        Returns
        -------
        (n+1, d) array
            Coefficients after expanding in polynomial basis, where :math:`n`
            is the degree of the BÃ©zier curve and :math:`d` its dimension.
            These are the numbers (:math:`C_j`) such that the curve can be
            written :math:`\sum_{j=0}^n C_j t^j`.

        Notes
        -----
        The coefficients are calculated as

        .. math::

            {n \choose j} \sum_{i=0}^j (-1)^{i+j} {j \choose i} P_i

        where :math:`P_i` are the control points of the curve.
        é
   zFPolynomial coefficients formula unstable for high order Bezier curves!r   Nr.   )r[   ÚwarningsÚwarnÚRuntimeWarningrR   r   r	   r   )rJ   r   ÚPÚjr   Z	prefactorr   r   r   Úpolynomial_coefficientsï   s    ÿz%BezierSegment.polynomial_coefficientsc           
      C   sà   | j }|dkr"t g ¡t g ¡fS | j}t d|d ¡dd…df |dd…  }g }g }t|jƒD ]8\}}t |ddd… ¡}| |¡ | t 	||¡¡ qbt 
|¡}t 
|¡}t |¡|dk@ |dk@ }	||	 t |¡|	 fS )aã  
        Return the dimension and location of the curve's interior extrema.

        The extrema are the points along the curve where one of its partial
        derivatives is zero.

        Returns
        -------
        dims : array of int
            Index :math:`i` of the partial derivative which is zero at each
            interior extrema.
        dzeros : array of float
            Of same size as dims. The :math:`t` such that :math:`d/dx_i B(t) =
            0`
        r   Nr.   r   )r[   r   Úarrayrb   r	   Ú	enumeraterP   Úrootsr4   Z	full_likeÚconcatenateZisrealÚreal)
rJ   r   ZCjZdCjZdimsre   r   ÚpiÚrZin_ranger   r   r   Úaxis_aligned_extrema  s    (


z"BezierSegment.axis_aligned_extremaN)r   r   r   Ú__doc__rS   rW   rY   ÚpropertyrR   rZ   r[   rb   rj   r   r   r   r   rE   µ   s   		



#rE   c           	      C   s>   t | ƒ}|j}t|||d�\}}t| || d ƒ\}}||fS )ur  
    Split a BÃ©zier curve into two at the intersection with a closed path.

    Parameters
    ----------
    bezier : (N, 2) array-like
        Control points of the BÃ©zier segment. See `.BezierSegment`.
    inside_closedpath : callable
        A function returning True if a given point (x, y) is inside the
        closed path. See also `.find_bezier_t_intersecting_with_closedpath`.
    tolerance : float
        The tolerance for the intersection. See also
        `.find_bezier_t_intersecting_with_closedpath`.

    Returns
    -------
    left, right
        Lists of control points for the two BÃ©zier segments.
    )r@   g       @)rE   rY   rD   r7   )	Zbezierr=   r@   Zbzr<   r>   r?   Ú_leftÚ_rightr   r   r   Ú)split_bezier_intersecting_with_closedpath4  s      ÿ
ro   Fc                 C   s  ddl m} |  ¡ }t|ƒ\}}||dd… ƒ}|}	d}
d}|D ]N\}}|}
|t|ƒd 7 }||dd… ƒ|krŠt |	dd… |g¡} q˜|}	q@tdƒ‚| d¡}t	|||ƒ\}}t|ƒdkrÔ|j
g}|j|j
g}nft|ƒd	krþ|j|jg}|j|j|jg}n<t|ƒd
k�r2|j|j|jg}|j|j|j|jg}ntdƒ‚|dd… }|dd… }| jdk�r˜|t | jd|… |g¡ƒ}|t || j|d… g¡ƒ}nd|t | jd|
… |g¡t | jd|
… |g¡ƒ}|t || j|d… g¡t || j|d… g¡ƒ}|�r|�s|| }}||fS )z`
    Divide a path into two segments at the point where ``inside(x, y)`` becomes
    False.
    r   )ÚPathéþÿÿÿNr   é   z*The path does not intersect with the patch)r.   rr   é   é   zThis should never be reached)Úpathrp   Úiter_segmentsÚnextr5   r   rf   r   Zreshapero   ZLINETOZMOVETOZCURVE3ZCURVE4ÚAssertionErrorÚcodesZvertices)ru   Zinsider@   Zreorder_inoutrp   Z	path_iterZ
ctl_pointsÚcommandZbegin_insideZctl_points_oldZioldr   Zbezier_pathÚbpÚleftÚrightZ
codes_leftZcodes_rightZ
verts_leftZverts_rightZpath_inZpath_outr   r   r   Úsplit_path_inoutW  sZ    
  ÿÿÿ
r~   c                    s   |d ‰‡ ‡‡fdd„}|S )zÎ
    Return a function that checks whether a point is in a circle with center
    (*cx*, *cy*) and radius *r*.

    The returned function has the signature::

        f(xy: tuple[float, float]) -> bool
    rr   c                    s$   | \}}|ˆ  d |ˆ d  ˆk S )Nrr   r   )Zxyr#   r$   ©r'   r(   Úr2r   r   Ú_fŸ  s    zinside_circle.<locals>._fr   )r'   r(   ri   r�   r   r   r   Úinside_circle”  s    	r‚   c                 C   sB   ||  ||  }}|| ||  d }|dkr2dS || || fS )Nr:   r   )r&   r&   r   )Zx0Zy0r*   r+   ZdxZdyr"   r   r   r   Úget_cos_sin§  s
    rƒ   çñhãˆµøä>c                 C   sN   t  | |¡}t  ||¡}t|| ƒ}||k r0dS t|t j ƒ|k rFdS dS dS )aË  
    Check if two lines are parallel.

    Parameters
    ----------
    dx1, dy1, dx2, dy2 : float
        The gradients *dy*/*dx* of the two lines.
    tolerance : float
        The angular tolerance in radians up to which the lines are considered
        parallel.

    Returns
    -------
    is_parallel
        - 1 if two lines are parallel in same direction.
        - -1 if two lines are parallel in opposite direction.
        - False otherwise.
    r   r.   FN)r   Zarctan2r   rh   )Zdx1Zdy1Zdx2Zdy2r@   Ztheta1Ztheta2Zdthetar   r   r   Úcheck_if_parallel°  s    r…   c              	   C   s~  | d \}}| d \}}| d \}}t || || || || ƒ}|dkrrt d¡ t||||ƒ\}	}
|	|
 }}n$t||||ƒ\}	}
t||||ƒ\}}t|||	|
|ƒ\}}}}t|||||ƒ\}}}}z8t|||	|
||||ƒ\}}t|||	|
||||ƒ\}}W nJ tk
�rH   d||  d||   }}d||  d||   }}Y nX ||f||f||fg}||f||f||fg}||fS )u­   
    Given the quadratic BÃ©zier control points *bezier2*, returns
    control points of quadratic BÃ©zier lines roughly parallel to given
    one separated by *width*.
    r   r   rr   r.   z8Lines do not intersect. A straight line is used instead.r:   )r…   r   Zwarn_externalrƒ   r-   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_parallelsÎ  sd     ÿÿÿ
ÿ
   þ   þ
 
ÿ
 
ÿþþr”   c                 C   s>   dd| | |   }dd| ||   }| |f||f||fgS )už   
    Find control points of the BÃ©zier curve passing through (*c1x*, *c1y*),
    (*mmx*, *mmy*), and (*c2x*, *c2y*), at parametric values 0, 0.5, and 1.
    r:   rt   r   )rˆ   r‰   ZmmxZmmyrŒ   r�   rŠ   r‹   r   r   r   Úfind_control_points  s    r•   r:   c           %      C   s(  | d \}}| d \}}| d \}	}
t ||||ƒ\}}t |||	|
ƒ\}}t|||||| ƒ\}}}}t|	|
|||| ƒ\}}}}|| d || d  }}||	 d ||
 d  }}|| d || d  }}t ||||ƒ\}}t|||||| ƒ\}} }!}"t|||| ||ƒ}#t|||!|"||ƒ}$|#|$fS )u¬   
    Being similar to `get_parallels`, returns control points of two quadratic
    BÃ©zier lines having a width roughly parallel to given one separated by
    *width*.
    r   r   rr   r:   )rƒ   r-   r•   )%r†   r‡   Zw1ZwmZw2rˆ   r‰   rŠ   r‹   Zc3xZc3yr   r   r   r   rŽ   r�   r�   r‘   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_rightr’   r“   r   r   r   Úmake_wedged_bezier2"  s8    ÿ
ÿ
ÿ
  þ  þr–   )r&   r8   r9   )r9   )r9   F)r„   )r8   r:   r&   )rk   Ú	functoolsr   rF   r]   Únumpyr   Z
matplotlibr   Z	vectorizer   r   r   r%   r-   r1   r7   rD   rE   ro   r~   r‚   rƒ   r…   r”   r•   r–   r   r   r   r   Ú<module>   s8   !     ÿ
D  ÿ
#
=	
J
