
    G8cH                         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               Z
 G d d	e      Zd
 Zd Zd Zd Z	 ddZ G d d      Z	 ddZddZd Zd ZddZd Zd ZddZy)uP   
A module providing some utility functions regarding Bézier path manipulation.
    )	lru_cacheN)_api   )maxsizec                     || kD  ryt        || |z
        }t        j                  d|dz         }t        j                  | dz   |z
  |z        j	                  t
              S )Nr      )minnparangeprodastypeint)nkis      3/usr/lib/python3/dist-packages/matplotlib/bezier.py_combr      sW     	1uAq1uA
		!QUA77AEAIq=!((--    c                       e Zd Zy)NonIntersectingPathExceptionN)__name__
__module____qualname__ r   r   r   r      s    r   r   c                    || z  ||z  z
  }||z  ||z  z
  }	|| }}
|| }}|
|z  ||z  z
  }t        |      dk  rt        d      || }}| |
}}||||fD cg c]  }||z  	 c}\  }}}}||z  ||	z  z   }||z  ||	z  z   }||fS c c}w )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.)abs
ValueError)cx1cy1cos_t1sin_t1cx2cy2cos_t2sin_t2	line1_rhs	line2_rhsabcdad_bca_b_c_d_r   xys                         r   get_intersectionr3       s     v|+Iv|+I F7qAF7qAEAEME
5zE N O 	O BRB*,b"b)9:Aa%i:NBB
Yi'A
Yi'Aa4K ;s   Bc                 x    |dk(  r| || |fS || }}| |}}||z  | z   ||z  |z   }
}	||z  | z   ||z  |z   }}|	|
||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cycos_tsin_tlengthr    r!   r$   r%   x1y1x2y2s                r   get_normal_pointsr?   A   ss     |2r2~UFFFVUFFf_r!6F?R#7Bf_r!6F?R#7Br2r>r   c                 .    | d d d|z
  z  | dd  |z  z   }|S )Nr   r   )betat	next_betas      r   _de_casteljau1rE   Z   s+    Sb	QU#d12hl2Ir   c                    t        j                  |       } | g}	 t        | |      } |j                  |        t	        |       dk(  rn-|D  cg c]  } | d   	 }} t        |      D  cg c]  } | d   	 }} ||fS c c} w c c} w )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   r   rA   )r
   asarrayrE   appendlenreversed)rB   rC   	beta_list	left_beta
right_betas        r   split_de_casteljaurN   _   s    
 ::dDI
dA&t9>	 
 &//Ta/I/'/	':;t$r(;J;j   0;s   A8&A=c                     | |      } | |      } ||      } ||      }||k(  r||k7  rt        d      	 t        j                  |d   |d   z
  |d   |d   z
        |k  r||fS d||z   z  }	 | |	      }
 ||
      }||z  r|	}|
}n|	}|
}|}X)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         ?)r   r
   hypot)bezier_point_at_tinside_closedpatht0t1	tolerancestartendstart_inside
end_insidemiddle_tmiddlemiddle_insides               r   *find_bezier_t_intersecting_with_closedpathr^   q   s    L b!E
B
C$U+L"3'Jz!esl*AC 	C  88E!Hs1v%uQx#a&'89IEr6M "r'?"8,)&1-'BCBE(L# r   c                   h    e Zd ZdZd Zd Zd Zed        Zed        Z	ed        Z
ed        Zd	 Zy
)BezierSegmentu   
    A d-dimensional Bézier segment.

    Parameters
    ----------
    control_points : (N, d) array
        Location of the *N* control points.
    c           	         t        j                  |      | _        | j                  j                  \  | _        | _        t        j                  | j                        | _        t        | j                        D cg c]`  }t        j                  | j                  dz
        t        j                  |      t        j                  | j                  dz
  |z
        z  z  b }}| j                  j                  |z  j                  | _        y c c}w )Nr   )r
   rG   _cpointsshape_N_dr   _ordersrangemath	factorialT_px)selfcontrol_pointsr   coeffs       r   __init__zBezierSegment.__init__   s    

>2==..yy)  .* !,^^A&!a)HHJ * * MMOOe+..*s   9A%D	c                    t        j                  |      }t         j                  j                  d|z
  | j                  ddd         t         j                  j                  || j                        z  | j
                  z  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   NrA   )r
   rG   powerouterrf   rk   rl   rC   s     r   __call__zBezierSegment.__call__   s`     JJqMq1udll4R4&89((..DLL1259XX> 	>r   c                 $    t         | |            S )zX
        Evaluate the curve at a single point, returning a tuple of *d* floats.
        )tuplers   s     r   
point_at_tzBezierSegment.point_at_t   s     T!W~r   c                     | j                   S )z The control points of the curve.)rb   rl   s    r   rm   zBezierSegment.control_points   s     }}r   c                     | j                   S )zThe dimension of the curve.)re   ry   s    r   	dimensionzBezierSegment.dimension   s     wwr   c                      | j                   dz
  S )z@Degree of the polynomial. One less the number of control points.r   )rd   ry   s    r   degreezBezierSegment.degree   s     ww{r   c                 :   | j                   }|dkD  rt        j                  dt               | j                  }t        j                  |dz         dddf   }t        j                  |dz         dddf   }d||z   z  t        ||      z  }t        ||      |z  |z  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   NrA   )r}   warningswarnRuntimeWarningrm   r
   r   r   )rl   r   Pjr   	prefactors         r   polynomial_coefficientsz%BezierSegment.polynomial_coefficients   s    2 KKr6MM 12@BIIacN1d7#IIacN47#1q5ME!QK/	Q{Y&**r   c                    | j                   }|dk  r*t        j                  g       t        j                  g       fS | j                  }t        j                  d|dz         dddf   |dd z  }g }g }t        |j                        D ]V  \  }}t        j                  |ddd         }|j                  |       |j                  t        j                  ||             X t        j                  |      }t        j                  |      }t        j                  |      |dk\  z  |dk  z  }	||	   t        j                  |      |	   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   NrA   r   )r}   r
   arrayr   r   	enumeraterj   rootsrH   	full_likeconcatenateisrealreal)
rl   r   CjdCjdimsr   r   pirin_ranges
             r   axis_aligned_extremaz"BezierSegment.axis_aligned_extrema  s     KK688B<"--))ii1Q34(2ab61suu% 	,EArDbD"ALLOKKQ*+	, u%~~d#99U#uz2eqjAH~rwwu~h777r   N)r   r   r   __doc__ro   rt   rw   propertyrm   r{   r}   r   r   r   r   r   r`   r`      sl    />$       !+ !+F8r   r`   c                     t        |       }|j                  }t        |||      \  }}t        | ||z   dz        \  }}||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.
    )rV   g       @)r`   rw   r^   rN   )	bezierrS   rV   bzrR   rT   rU   _left_rights	            r   )split_bezier_intersecting_with_closedpathr   4  sS    , 
v	B7,	CFB 'vR2~>ME6&=r   c           	      J   ddl m} | j                         }t        |      \  }} ||dd       }|}	d}
d}|D ]D  \  }}|}
|t	        |      dz  z  } ||dd       |k7  rt        j                  |	dd |g      } n|}	F t        d      |j                  d      }t        |||      \  }}t	        |      dk(  r&|j                  g}|j                  |j                  g}nt	        |      d	k(  r<|j                  |j                  g}|j                  |j                  |j                  g}nkt	        |      d
k(  rR|j                  |j                  |j                  g}|j                  |j                  |j                  |j                  g}nt        d      |dd }|dd }| j                  U |t        j                  | j                   d| |g            } |t        j                  || j                   |d g            }n |t        j                  | j                   d|
 |g      t        j                  | j                  d|
 |g            } |t        j                  || j                   |d g      t        j                  || j                  |d g            }|r|s||}}||fS )z`
    Divide a path into two segments at the point where ``inside(x, y)`` becomes
    False.
    r   )PathNr      z*The path does not intersect with the patch)rA   r         zThis should never be reached)pathr   iter_segmentsnextrI   r
   r   r   reshaper   LINETOMOVETOCURVE3CURVE4AssertionErrorcodesvertices)r   insiderV   reorder_inoutr   	path_iter
ctl_pointscommandbegin_insidectl_points_oldioldr   bezier_pathbpleftright
codes_leftcodes_right
verts_leftverts_rightpath_inpath_outs                         r   split_path_inoutr   W  s   
 ""$Iy/J*RS/*LND	A( G
G	S_!!*RS/"l2...*=z)JKK#G EFF			W	%B;
FIKD%
4yA~kk]
{{DKK0	Takk4;;/
{{DKK=	Takk4;;<
{{DKKdkkJ;<<abJ(Kzzr~~t}}Ra'8*&EFGT]]125F'GHI r~~t}}Ud';Z&HI~~tzz%4'8*&EFH T]]125F'GHTZZ^'DEG \$gHr   c                 $     |dz   f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
    r   c                 6    | \  }}|z
  dz  |z
  dz  z   k  S )Nr   r   )xyr1   r2   r6   r7   r2s      r   _fzinside_circle.<locals>._f  s,    1B1}B1},r11r   r   )r6   r7   r   r   r   s   ``  @r   inside_circler     s     
aB2 Ir   c                 R    || z
  ||z
  }}||z  ||z  z   dz  }|dk(  ry||z  ||z  fS )NrP   r   )r5   r5   r   )x0y0r;   r<   dxdyr+   s          r   get_cos_sinr     sF    "Wb2gB	b27	r!AAv626>r   c                     t        j                  | |      }t        j                  ||      }t        ||z
        }||k  ryt        |t         j                  z
        |k  ryy)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   rA   F)r
   arctan2r   r   )dx1dy1dx2dy2rV   theta1theta2dthetas           r   check_if_parallelr     sX    & ZZS!FZZS!F&!F		Vbee^	y	(r   c           
      B   | d   \  }}| d   \  }}| d   \  }}t        ||z
  ||z
  ||z
  ||z
        }|dk(  r+t        j                  d       t        ||||      \  }	}
|	|
}}n"t        ||||      \  }	}
t        ||||      \  }}t	        |||	|
|      \  }}}}t	        |||||      \  }}}}	 t        |||	|
||||      \  }}t        |||	|
||||      \  }}||f||f||fg}||f||f||fg}||fS # t        $ r# d||z   z  d||z   z  }}d||z   z  d||z   z  }}Y Ew xY w)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   r   rA   z8Lines do not intersect. A straight line is used instead.rP   )r   r   warn_externalr   r?   r3   r   )bezier2widthc1xc1ycmxcmyc2xc2yparallel_testr    r!   r$   r%   c1x_leftc1y_left	c1x_right	c1y_rightc2x_leftc2y_left	c2x_right	c2y_rightcmx_leftcmy_left	cmx_right	cmy_right	path_left
path_rights                              r   get_parallelsr     s    qzHCqzHCqzHC%cCis&)Cis<M F	H$S#sC8 %S#sC8$S#sC8 	#sFFE: -Hh	9 	#sFFE: -Hh	9
-h&.4h.4f>(  0	9f06	906 @	9  H%H%H%'I i(i(i(*J j  )  	

 8h&'80C)D  9y()3)i2G+H 		
s   .*C2 2)DDc                 P    dd|z  | |z   z
  z  }dd|z  ||z   z
  z  }| |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.
    rP   r   r   )r   r   mmxmmyr   r   r   r   s           r   find_control_pointsr     sK    
 C39%
&C
C39%
&C#Jc
S#J//r   c                    | d   \  }}| d   \  }}| d   \  }	}
t        ||||      \  }}t        |||	|
      \  }}t        ||||||z        \  }}}}t        |	|
||||z        \  }}}}||z   dz  ||z   dz  }}||	z   dz  ||
z   dz  }}||z   dz  ||z   dz  }}t        ||||      \  }}t        ||||||z        \  }} }!}"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   r   rP   )r   r?   r   )%r   r   w1wmw2r   r   r   r   c3xc3yr    r!   r$   r%   r   r   r   r   c3x_leftc3y_left	c3x_right	c3y_rightc12xc12yc23xc23yc123xc123ycos_t123sin_t123
c123x_left
c123y_leftc123x_rightc123y_rightr   r   s%                                        r   make_wedged_bezier2r  "  si    qzHCqzHCqzHC !c34NFF c34NFF 	#sFFEBJ? -Hh	9 	#sFFEBJ? -Hh	9 )r!C#I#3$D)r!C#I#3$D4K2%tr'95E %T4t<Hh 	%(EBJG 5J
K $Hh$.
$,h8I %Y	%0+%.	;J j  r   )r5         ?{Gz?)r  )r  F)gh㈵>)r  rP   r5   )r   	functoolsr   rh   r   numpyr
   
matplotlibr   	vectorizer   r   r   r3   r?   rE   rN   r^   r`   r   r   r   r   r   r   r   r  r   r   r   <module>r     s          
3.  .	: 	B2
!& GKA)H|8 |8@ .2F:z&<G!T00!r   