U
    ºmœd�¬  ã                   @   sœ  d Z ddlmZmZmZ ddlmZ ddlZddlm	Z	 zddl
Z
e
jZW n( eefk
rr   ddlm
Z
 dZY nX e	dd	d
dgƒZddddddddddddddddddddd d!d"d#d$d%d&d'gZd‰d)d„Zd*d+„ Ze
 e
j¡e
je
je
je
je
jd,�e
je
je
je
jd-�d.d/„ ƒƒƒZe
 e
j¡e
je
je
je
je
jd0�e
je
je
jd1�dŠd2d„ƒƒƒZd3Zd4Ze
je
je
 e
j¡e
je
je
jd5�d6d7„ ƒƒƒƒZe
je
je
 e
j¡e
je
jd8�d9d:„ ƒƒƒƒZd;d„ Z e
 e
j¡e
je
je
je
je
je
je
je
jd<�e
je
je
je
je
je
je
je
jd=�d>d„ ƒƒƒZ!d?d„ Z"e
 e
j¡e
je
je
je
jd@�e
je
je
je
jdA�dBd„ ƒƒƒZ#dCd„ Z$dDd„ Z%e
 e
j¡e
je
je
je
je
jd0�e
je
je
je
je
je
jdE�dFd„ ƒƒƒZ&dGd„ Z'dHd„ Z(dId„ Z)dJd„ Z*dKd„ Z+dLd„ Z,e
je
je
je
je
je
je
je
je
jdM�dNd„ ƒZ-e
 e
j¡e
je
je
je
je
je
je
je
je
jdO�e
je
je
je
je
jdP�dQd„ ƒƒƒZ.dRdS„ Z/dTdU„ Z0e
je
je
je
je
je
je
je
je
je
je
je
je
je
jdV�dWdX„ ƒZ1ddYlm2Z2m3Z3m4Z4m5Z5 e2fdZd„Z6d[d„ Z7d\d]„ Z8d^d_„ Z9e
je
je
je
je
je
je
je
je
je
jd`�dadb„ ƒƒƒZ:dcdd„ Z;dedf„ Z<e
je
je
je
je
je
je
je
je
je
jdg�dhdi„ ƒƒƒZ=djd"„ Z>dkd„ Z?dld „ Z@e
 e
j¡e
je
je
je
je
je
jdm�e
je
je
je
jdn�dod!„ ƒƒƒZAdpd#„ ZBdqdr„ ZCdsdt„ ZDdud$„ ZEdvdw„ ZFdxdy„ ZGdzd%„ ZHd{d|„ ZId}d~„ ZJd‹d€d�„ZKd‚d&„ ZLdƒd'„ ZMd„d…„ ZNd†d‡„ ZOePdˆk�r˜ddlQZQddlRZReQ SeR T¡ jU¡ dS )ŒzNfontTools.misc.bezierTools.py -- tools for working with Bezier path segments.
é    )Ú
calcBoundsÚsectRectÚrectArea)ÚIdentityN)Ú
namedtuple)ÚcythonFÚIntersectionÚptÚt1Út2ÚapproximateCubicArcLengthÚapproximateCubicArcLengthCÚapproximateQuadraticArcLengthÚapproximateQuadraticArcLengthCÚcalcCubicArcLengthÚcalcCubicArcLengthCÚcalcQuadraticArcLengthÚcalcQuadraticArcLengthCÚcalcCubicBoundsÚcalcQuadraticBoundsÚ	splitLineÚsplitQuadraticÚ
splitCubicÚsplitQuadraticAtTÚsplitCubicAtTÚsplitCubicAtTCÚsplitCubicIntoTwoAtTCÚsolveQuadraticÚ
solveCubicÚquadraticPointAtTÚcubicPointAtTÚcubicPointAtTCÚlinePointAtTÚsegmentPointAtTÚlineLineIntersectionsÚcurveLineIntersectionsÚcurveCurveIntersectionsÚsegmentSegmentIntersectionsç{®Gázt?c                 C   s    t t| Ž t|Ž t|Ž t|Ž |ƒS )aÄ  Calculates the arc length for a cubic Bezier segment.

    Whereas :func:`approximateCubicArcLength` approximates the length, this
    function calculates it by "measuring", recursively dividing the curve
    until the divided segments are shorter than ``tolerance``.

    Args:
        pt1,pt2,pt3,pt4: Control points of the Bezier as 2D tuples.
        tolerance: Controls the precision of the calcuation.

    Returns:
        Arc length value.
    )r   Úcomplex)Úpt1Úpt2Úpt3Úpt4Ú	tolerance© r/   úS/home/sam/Atlas/atlas_env/lib/python3.8/site-packages/fontTools/misc/bezierTools.pyr   8   s        ÿc                 C   s\   | d||   | d }|| | |  d }| | | d || |f||| || d |ffS )Né   g      À?ç      à?r/   )Úp0Úp1Úp2Úp3ÚmidZderiv3r/   r/   r0   Ú_split_cubic_into_twoK   s
    þr8   )r3   r4   r5   r6   )ÚmultÚarchÚboxc           	      C   sz   t || ƒ}t || ƒt || ƒ t || ƒ }||  |krH|| d S t||||ƒ\}}t| f|žŽ t| f|žŽ  S d S ©Nr2   )Úabsr8   Ú_calcCubicArcLengthCRecurse)	r9   r3   r4   r5   r6   r:   r;   ÚoneÚtwor/   r/   r0   r>   T   s    	$ÿÿr>   ©r*   r+   r,   r-   )r.   r9   c                 C   s   dd|  }t || |||ƒS )zôCalculates the arc length for a cubic Bezier segment.

    Args:
        pt1,pt2,pt3,pt4: Control points of the Bezier as complex numbers.
        tolerance: Controls the precision of the calcuation.

    Returns:
        Arc length value.
    ç      ð?g      ø?)r>   )r*   r+   r,   r-   r.   r9   r/   r/   r0   r   h   s    é   g»½×Ùß|Û=©Úv1Úv2c                 C   s   | |  ¡  jS ©N)Ú	conjugateÚrealrD   r/   r/   r0   Ú_dot…   s    rJ   ©Úxc                 C   s(   | t  | d d ¡ d t  | ¡d  S )Né   é   )ÚmathÚsqrtÚasinhrK   r/   r/   r0   Ú_intSecAtan�   s    rR   c                 C   s   t t| Ž t|Ž t|Ž ƒS )až  Calculates the arc length for a quadratic Bezier segment.

    Args:
        pt1: Start point of the Bezier as 2D tuple.
        pt2: Handle point of the Bezier as 2D tuple.
        pt3: End point of the Bezier as 2D tuple.

    Returns:
        Arc length value.

    Example::

        >>> calcQuadraticArcLength((0, 0), (0, 0), (0, 0)) # empty segment
        0.0
        >>> calcQuadraticArcLength((0, 0), (50, 0), (80, 0)) # collinear points
        80.0
        >>> calcQuadraticArcLength((0, 0), (0, 50), (0, 80)) # collinear points vertical
        80.0
        >>> calcQuadraticArcLength((0, 0), (50, 20), (100, 40)) # collinear points
        107.70329614269008
        >>> calcQuadraticArcLength((0, 0), (0, 100), (100, 0))
        154.02976155645263
        >>> calcQuadraticArcLength((0, 0), (0, 50), (100, 0))
        120.21581243984076
        >>> calcQuadraticArcLength((0, 0), (50, -10), (80, 50))
        102.53273816445825
        >>> calcQuadraticArcLength((0, 0), (40, 0), (-40, 0)) # collinear points, control point outside
        66.66666666666667
        >>> calcQuadraticArcLength((0, 0), (40, 0), (0, 0)) # collinear points, looping back
        40.0
    )r   r)   ©r*   r+   r,   r/   r/   r0   r   —   s     )r*   r+   r,   Úd0Úd1ÚdÚn)ÚscaleÚorigDistÚaÚbÚx0Úx1ÚLenc                 C   sÞ   ||  }|| }|| }|d }t |ƒ}|dkr<t ||  ƒS t||ƒ}t |ƒtk r–t||ƒdkrlt ||  ƒS t |ƒt |ƒ }	}
|	|	 |
|
  |	|
  S t||ƒ| }t||ƒ| }t dt|ƒt|ƒ  | |||   ƒ}|S )a$  Calculates the arc length for a quadratic Bezier segment.

    Args:
        pt1: Start point of the Bezier as a complex number.
        pt2: Handle point of the Bezier as a complex number.
        pt3: End point of the Bezier as a complex number.

    Returns:
        Arc length value.
    y              ð?ç        r   rM   )r=   rJ   ÚepsilonrR   )r*   r+   r,   rT   rU   rV   rW   rX   rY   rZ   r[   r\   r]   r^   r/   r/   r0   r   º   s"     
(c                 C   s   t t| Ž t|Ž t|Ž ƒS )a«  Calculates the arc length for a quadratic Bezier segment.

    Uses Gauss-Legendre quadrature for a branch-free approximation.
    See :func:`calcQuadraticArcLength` for a slower but more accurate result.

    Args:
        pt1: Start point of the Bezier as 2D tuple.
        pt2: Handle point of the Bezier as 2D tuple.
        pt3: End point of the Bezier as 2D tuple.

    Returns:
        Approximate arc length value.
    )r   r)   rS   r/   r/   r0   r   í   s    rS   )Úv0rE   rF   c                 C   sT   t d|  d|  d|  ƒ}t ||  ƒd }t d|  d|  d|  ƒ}|| | S )aÃ  Calculates the arc length for a quadratic Bezier segment.

    Uses Gauss-Legendre quadrature for a branch-free approximation.
    See :func:`calcQuadraticArcLength` for a slower but more accurate result.

    Args:
        pt1: Start point of the Bezier as a complex number.
        pt2: Handle point of the Bezier as a complex number.
        pt3: End point of the Bezier as a complex number.

    Returns:
        Approximate arc length value.
    gÌ”xùbŒß¿g¾ðb�ŠÛ?gF�V¨W°?gÇqÇqÜ?gF�V¨W°¿gÌ”xùbŒß?©r=   )r*   r+   r,   ra   rE   rF   r/   r/   r0   r   þ   s    !ÿÿc                    sŽ   t | ||ƒ\\‰ ‰\‰‰\‰‰ˆ d }ˆd }g }|dkrJ| ˆ | ¡ |dkrb| ˆ | ¡ ‡ ‡‡‡‡‡fdd„|D ƒ| |g }t|ƒS )a  Calculates the bounding rectangle for a quadratic Bezier segment.

    Args:
        pt1: Start point of the Bezier as a 2D tuple.
        pt2: Handle point of the Bezier as a 2D tuple.
        pt3: End point of the Bezier as a 2D tuple.

    Returns:
        A four-item tuple representing the bounding rectangle ``(xMin, yMin, xMax, yMax)``.

    Example::

        >>> calcQuadraticBounds((0, 0), (50, 100), (100, 0))
        (0, 0, 100, 50.0)
        >>> calcQuadraticBounds((0, 0), (100, 0), (100, 100))
        (0.0, 0.0, 100, 100)
    ç       @r   c                    sT   g | ]L}d |  krdk rn qˆ | | ˆ|  ˆ ˆ| | ˆ|  ˆ f‘qS ©r   rN   r/   ©Ú.0Út©ÚaxÚayÚbxÚbyÚcxÚcyr/   r0   Ú
<listcomp>D  s
    
 þz'calcQuadraticBounds.<locals>.<listcomp>)ÚcalcQuadraticParametersÚappendr   )r*   r+   r,   Zax2Zay2ÚrootsÚpointsr/   rh   r0   r   *  s    þüc                 C   s   t t| Ž t|Ž t|Ž t|Ž ƒS )a®  Approximates the arc length for a cubic Bezier segment.

    Uses Gauss-Lobatto quadrature with n=5 points to approximate arc length.
    See :func:`calcCubicArcLength` for a slower but more accurate result.

    Args:
        pt1,pt2,pt3,pt4: Control points of the Bezier as 2D tuples.

    Returns:
        Arc length value.

    Example::

        >>> approximateCubicArcLength((0, 0), (25, 100), (75, 100), (100, 0))
        190.04332968932817
        >>> approximateCubicArcLength((0, 0), (50, 0), (100, 50), (100, 100))
        154.8852074945903
        >>> approximateCubicArcLength((0, 0), (50, 0), (100, 0), (150, 0)) # line; exact result should be 150.
        149.99999999999991
        >>> approximateCubicArcLength((0, 0), (50, 0), (100, 0), (-50, 0)) # cusp; exact result should be 150.
        136.9267662156362
        >>> approximateCubicArcLength((0, 0), (50, 0), (100, -50), (-50, 0)) # cusp
        154.80848416537057
    )r   r)   rA   r/   r/   r0   r   L  s       ÿ)ra   rE   rF   Úv3Úv4c           	      C   s”   t ||  ƒd }t d|  d|  d|  d|  ƒ}t ||  | | ƒd }t d|  d|  d|  d|  ƒ}t || ƒd }|| | | | S )	z¹Approximates the arc length for a cubic Bezier segment.

    Args:
        pt1,pt2,pt3,pt4: Control points of the Bezier as complex numbers.

    Returns:
        Arc length value.
    g333333Ã?g�c’‰1ãá¿g8Ø5$t×Ô?guÁ|Yù¿Ê?gæâ#$ï˜?gÑ?gæâ#$ï˜¿g�c’‰1ãá?rb   )	r*   r+   r,   r-   ra   rE   rF   rt   ru   r/   r/   r0   r   j  s,    ÿþýÿÿþýÿc                    sª   t | |||ƒ\\‰ ‰\‰‰\‰‰\‰‰ˆ d }ˆd }ˆd }ˆd }dd„ t||ˆƒD ƒ}dd„ t||ˆƒD ƒ}	||	 }
‡ ‡‡‡‡‡‡‡fdd„|
D ƒ| |g }t|ƒS )aX  Calculates the bounding rectangle for a quadratic Bezier segment.

    Args:
        pt1,pt2,pt3,pt4: Control points of the Bezier as 2D tuples.

    Returns:
        A four-item tuple representing the bounding rectangle ``(xMin, yMin, xMax, yMax)``.

    Example::

        >>> calcCubicBounds((0, 0), (25, 100), (75, 100), (100, 0))
        (0, 0, 100, 75.0)
        >>> calcCubicBounds((0, 0), (50, 0), (100, 50), (100, 100))
        (0.0, 0.0, 100, 100)
        >>> print("%f %f %f %f" % calcCubicBounds((50, 0), (0, 100), (100, 100), (50, 0)))
        35.566243 0.000000 64.433757 75.000000
    ç      @rc   c                 S   s(   g | ] }d |  krdk rn q|‘qS rd   r/   re   r/   r/   r0   ro   ´  s
      
  z#calcCubicBounds.<locals>.<listcomp>c                 S   s(   g | ] }d |  krdk rn q|‘qS rd   r/   re   r/   r/   r0   ro   µ  s
      
  c                    s\   g | ]T}ˆ | | | ˆ| |  ˆ|  ˆ ˆ| | | ˆ| |  ˆ|  ˆ f‘qS r/   r/   re   ©ri   rj   rk   rl   rm   rn   ÚdxÚdyr/   r0   ro   ¸  s   ý&&þ)ÚcalcCubicParametersr   r   )r*   r+   r,   r-   Zax3Zay3Zbx2Zby2ZxRootsZyRootsrr   rs   r/   rw   r0   r   œ  s    &ûúc                 C   s¨   | \}}|\}}|| }|| }	|}
|}||	f| }|dkrF| |fgS ||
|f|  | }d|  krndk ršn n(|| |
 |	| | f}| |f||fgS | |fgS dS )a  Split a line at a given coordinate.

    Args:
        pt1: Start point of line as 2D tuple.
        pt2: End point of line as 2D tuple.
        where: Position at which to split the line.
        isHorizontal: Direction of the ray splitting the line. If true,
            ``where`` is interpreted as a Y coordinate; if false, then
            ``where`` is interpreted as an X coordinate.

    Returns:
        A list of two line segments (each line segment being two 2D tuples)
        if the line was successfully split, or a list containing the original
        line.

    Example::

        >>> printSegments(splitLine((0, 0), (100, 100), 50, True))
        ((0, 0), (50, 50))
        ((50, 50), (100, 100))
        >>> printSegments(splitLine((0, 0), (100, 100), 100, True))
        ((0, 0), (100, 100))
        >>> printSegments(splitLine((0, 0), (100, 100), 0, True))
        ((0, 0), (0, 0))
        ((0, 0), (100, 100))
        >>> printSegments(splitLine((0, 0), (100, 100), 0, False))
        ((0, 0), (0, 0))
        ((0, 0), (100, 100))
        >>> printSegments(splitLine((100, 0), (0, 0), 50, False))
        ((100, 0), (50, 0))
        ((50, 0), (0, 0))
        >>> printSegments(splitLine((0, 100), (0, 0), 50, True))
        ((0, 100), (0, 50))
        ((0, 50), (0, 0))
    r   rN   Nr/   )r*   r+   ÚwhereÚisHorizontalZpt1xZpt1yZpt2xZpt2yri   rj   rk   rl   rZ   rg   ZmidPtr/   r/   r0   r   Â  s    $
c           	      C   sb   t | ||ƒ\}}}t|| || || | ƒ}tdd„ |D ƒƒ}|sP| ||fgS t|||f|žŽ S )a  Split a quadratic Bezier curve at a given coordinate.

    Args:
        pt1,pt2,pt3: Control points of the Bezier as 2D tuples.
        where: Position at which to split the curve.
        isHorizontal: Direction of the ray splitting the curve. If true,
            ``where`` is interpreted as a Y coordinate; if false, then
            ``where`` is interpreted as an X coordinate.

    Returns:
        A list of two curve segments (each curve segment being three 2D tuples)
        if the curve was successfully split, or a list containing the original
        curve.

    Example::

        >>> printSegments(splitQuadratic((0, 0), (50, 100), (100, 0), 150, False))
        ((0, 0), (50, 100), (100, 0))
        >>> printSegments(splitQuadratic((0, 0), (50, 100), (100, 0), 50, False))
        ((0, 0), (25, 50), (50, 50))
        ((50, 50), (75, 50), (100, 0))
        >>> printSegments(splitQuadratic((0, 0), (50, 100), (100, 0), 25, False))
        ((0, 0), (12.5, 25), (25, 37.5))
        ((25, 37.5), (62.5, 75), (100, 0))
        >>> printSegments(splitQuadratic((0, 0), (50, 100), (100, 0), 25, True))
        ((0, 0), (7.32233, 14.6447), (14.6447, 25))
        ((14.6447, 25), (50, 75), (85.3553, 25))
        ((85.3553, 25), (92.6777, 14.6447), (100, -7.10543e-15))
        >>> # XXX I'm not at all sure if the following behavior is desirable:
        >>> printSegments(splitQuadratic((0, 0), (50, 100), (100, 0), 50, True))
        ((0, 0), (25, 50), (50, 50))
        ((50, 50), (50, 50), (50, 50))
        ((50, 50), (75, 50), (100, 0))
    c                 s   s*   | ]"}d |  krdk rn q|V  qdS ©r   rN   Nr/   re   r/   r/   r0   Ú	<genexpr>"  s
      
  z!splitQuadratic.<locals>.<genexpr>)rp   r   ÚsortedÚ_splitQuadraticAtT)	r*   r+   r,   r{   r|   rZ   r[   ÚcÚ	solutionsr/   r/   r0   r   û  s    #  
ÿc                 C   sp   t | |||ƒ\}}}}	t|| || || |	| | ƒ}
tdd„ |
D ƒƒ}
|
s\| |||fgS t||||	f|
žŽ S )aÞ  Split a cubic Bezier curve at a given coordinate.

    Args:
        pt1,pt2,pt3,pt4: Control points of the Bezier as 2D tuples.
        where: Position at which to split the curve.
        isHorizontal: Direction of the ray splitting the curve. If true,
            ``where`` is interpreted as a Y coordinate; if false, then
            ``where`` is interpreted as an X coordinate.

    Returns:
        A list of two curve segments (each curve segment being four 2D tuples)
        if the curve was successfully split, or a list containing the original
        curve.

    Example::

        >>> printSegments(splitCubic((0, 0), (25, 100), (75, 100), (100, 0), 150, False))
        ((0, 0), (25, 100), (75, 100), (100, 0))
        >>> printSegments(splitCubic((0, 0), (25, 100), (75, 100), (100, 0), 50, False))
        ((0, 0), (12.5, 50), (31.25, 75), (50, 75))
        ((50, 75), (68.75, 75), (87.5, 50), (100, 0))
        >>> printSegments(splitCubic((0, 0), (25, 100), (75, 100), (100, 0), 25, True))
        ((0, 0), (2.29379, 9.17517), (4.79804, 17.5085), (7.47414, 25))
        ((7.47414, 25), (31.2886, 91.6667), (68.7114, 91.6667), (92.5259, 25))
        ((92.5259, 25), (95.202, 17.5085), (97.7062, 9.17517), (100, 1.77636e-15))
    c                 s   s*   | ]"}d |  krdk rn q|V  qdS r}   r/   re   r/   r/   r0   r~   G  s
      
  zsplitCubic.<locals>.<genexpr>)rz   r   r   Ú_splitCubicAtT)r*   r+   r,   r-   r{   r|   rZ   r[   r�   rV   r‚   r/   r/   r0   r   (  s       
ÿc                 G   s$   t | ||ƒ\}}}t|||f|žŽ S )a•  Split a quadratic Bezier curve at one or more values of t.

    Args:
        pt1,pt2,pt3: Control points of the Bezier as 2D tuples.
        *ts: Positions at which to split the curve.

    Returns:
        A list of curve segments (each curve segment being three 2D tuples).

    Examples::

        >>> printSegments(splitQuadraticAtT((0, 0), (50, 100), (100, 0), 0.5))
        ((0, 0), (25, 50), (50, 50))
        ((50, 50), (75, 50), (100, 0))
        >>> printSegments(splitQuadraticAtT((0, 0), (50, 100), (100, 0), 0.5, 0.75))
        ((0, 0), (25, 50), (50, 50))
        ((50, 50), (62.5, 50), (75, 37.5))
        ((75, 37.5), (87.5, 25), (100, 0))
    )rp   r€   )r*   r+   r,   ÚtsrZ   r[   r�   r/   r/   r0   r   M  s    c           	      G   s*   t | |||ƒ\}}}}t||||f|žŽ S )a   Split a cubic Bezier curve at one or more values of t.

    Args:
        pt1,pt2,pt3,pt4: Control points of the Bezier as 2D tuples.
        *ts: Positions at which to split the curve.

    Returns:
        A list of curve segments (each curve segment being four 2D tuples).

    Examples::

        >>> printSegments(splitCubicAtT((0, 0), (25, 100), (75, 100), (100, 0), 0.5))
        ((0, 0), (12.5, 50), (31.25, 75), (50, 75))
        ((50, 75), (68.75, 75), (87.5, 50), (100, 0))
        >>> printSegments(splitCubicAtT((0, 0), (25, 100), (75, 100), (100, 0), 0.5, 0.75))
        ((0, 0), (12.5, 50), (31.25, 75), (50, 75))
        ((50, 75), (59.375, 75), (68.75, 68.75), (77.3438, 56.25))
        ((77.3438, 56.25), (85.9375, 43.75), (93.75, 25), (100, 0))
    )rz   rƒ   ©	r*   r+   r,   r-   r„   rZ   r[   r�   rV   r/   r/   r0   r   e  s    )r*   r+   r,   r-   rZ   r[   r�   rV   c           	      g   s4   t | |||ƒ\}}}}t||||f|žŽ E dH  dS )a  Split a cubic Bezier curve at one or more values of t.

    Args:
        pt1,pt2,pt3,pt4: Control points of the Bezier as complex numbers..
        *ts: Positions at which to split the curve.

    Yields:
        Curve segments (each curve segment being four complex numbers).
    N)ÚcalcCubicParametersCÚ_splitCubicAtTCr…   r/   r/   r0   r   }  s    )rg   r*   r+   r,   r-   ÚpointAtTÚoff1Úoff2)r   Ú_1_tÚ_1_t_2Ú_2_t_1_tc                 C   sÀ   || }d| }|| }d| | }|| |  d|| | || |    || |  }	||  ||  ||  }
|| ||  ||  }| ||  |  }||| |  }| ||
|	f|	|||ffS )a  Split a cubic Bezier curve at t.

    Args:
        pt1,pt2,pt3,pt4: Control points of the Bezier as complex numbers.
        t: Position at which to split the curve.

    Returns:
        A tuple of two curve segments (each curve segment being four complex numbers).
    rN   rM   r1   r/   )r*   r+   r,   r-   rg   r   r‹   rŒ   r�   rˆ   r‰   rŠ   r/   r/   r0   r   •  s    2ÿc                 G   s  t |ƒ}g }| dd¡ | d¡ | \}}|\}}|\}	}
tt|ƒd ƒD ]¾}|| }||d  }|| }|| }|| }|| }d| | | | }d| | | | }|| }|| ||  |	 }|| ||  |
 }t||f||f||fƒ\}}}| |||f¡ qJ|S )Nr   r_   rB   rN   rM   )ÚlistÚinsertrq   ÚrangeÚlenÚcalcQuadraticPoints)rZ   r[   r�   r„   Úsegmentsri   rj   rk   rl   rm   rn   Úir
   r   ÚdeltaÚdelta_2Úa1xÚa1yÚb1xÚb1yÚt1_2Úc1xÚc1yr*   r+   r,   r/   r/   r0   r€   ½  s,    
r€   c           "      G   s‚  t |ƒ}| dd¡ | d¡ g }| \}}|\}}	|\}
}|\}}tt|ƒd ƒD �](}|| }||d  }|| }|| }|| }|| }|| }|| }|| }d| | | | }d| | |	 | }d| | |
 d| |  | }d|	 | | d| |  | }|| ||  |
|  | }|| |	|  ||  | }t||f||f||f||fƒ\}}} }!| ||| |!f¡ qR|S ©Nr   r_   rB   rN   r1   rM   )rŽ   r�   rq   r�   r‘   ÚcalcCubicPoints)"rZ   r[   r�   rV   r„   r“   ri   rj   rk   rl   rm   rn   rx   ry   r”   r
   r   r•   r–   Údelta_3r›   Út1_3r—   r˜   r™   rš   rœ   r�   Zd1xZd1yr*   r+   r,   r-   r/   r/   r0   rƒ   Ø  s@    
     ÿrƒ   )rZ   r[   r�   rV   r
   r   r•   r–   r    Úa1Úb1Úc1rU   c                 g   sð   t |ƒ}| dd¡ | d¡ tt|ƒd ƒD ]¼}|| }||d  }|| }|| }	||	 }
|| }|| }| |
 }d|  | | |	 }d| | | d|  |  | }| | ||  ||  | }t||||ƒ\}}}}||||fV  q.d S rž   )rŽ   r�   rq   r�   r‘   ÚcalcCubicPointsC)rZ   r[   r�   rV   r„   r”   r
   r   r•   r–   r    r›   r¡   r¢   r£   r¤   rU   r*   r+   r,   r-   r/   r/   r0   r‡   û  s"    
 r‡   )rP   ÚacosÚcosÚpic                 C   s~   t | ƒtk r,t |ƒtk rg }qz| | g}nN|| d|  |  }|dkrv||ƒ}| | d |  | | d |  g}ng }|S )uK  Solve a quadratic equation.

    Solves *a*x*x + b*x + c = 0* where a, b and c are real.

    Args:
        a: coefficient of *xÂ²*
        b: coefficient of *x*
        c: constant term

    Returns:
        A list of roots. Note that the returned list is neither guaranteed to
        be sorted nor to contain unique values!
    ç      @r_   rc   ©r=   r`   )rZ   r[   r�   rP   rr   ZDDZrDDr/   r/   r0   r   (  s    &c                 C   sŽ  t | ƒtk rt|||ƒS t| ƒ} ||  }||  }||  }|| d|  d }d| | | d| |  d|  d }|| }	|| | }
|	tk r”dn|	}	t |
ƒtk r¨dn|
}
|	|
 }|	dkrÞ|
dkrÞt| d tƒ}|||gS |td k�r@ttt|t	|
ƒ d	ƒd
ƒƒ}dt	|ƒ }|d }|t
|d ƒ | }|t
|dt  d ƒ | }|t
|dt  d ƒ | }t|||gƒ\}}}|| tk �r¸|| tk �r¸t|| | d tƒ } }}n~|| tk �rèt|| d tƒ }}t|tƒ}nN|| tk �rt|tƒ}t|| d tƒ }}nt|tƒ}t|tƒ}t|tƒ}|||gS tt	|ƒt |ƒ dƒ}|||  }|dk�rr| }t||d  tƒ}|gS dS )ut  Solve a cubic equation.

    Solves *a*x*x*x + b*x*x + c*x + d = 0* where a, b, c and d are real.

    Args:
        a: coefficient of *xÂ³*
        b: coefficient of *xÂ²*
        c: coefficient of *x*
        d: constant term

    Returns:
        A list of roots. Note that the returned list is neither guaranteed to
        be sorted nor to contain unique values!

    Examples::

        >>> solveCubic(1, 1, -6, 0)
        [-3.0, -0.0, 2.0]
        >>> solveCubic(-10.0, -9.0, 48.0, -29.0)
        [-2.9, 1.0, 1.0]
        >>> solveCubic(-9.875, -9.0, 47.625, -28.75)
        [-2.911392, 1.0, 1.0]
        >>> solveCubic(1.0, -4.5, 6.75, -3.375)
        [1.5, 1.5, 1.5]
        >>> solveCubic(-12.0, 18.0, -9.0, 1.50023651123)
        [0.5, 0.5, 0.5]
        >>> solveCubic(
        ...     9.0, 0.0, 0.0, -7.62939453125e-05
        ... ) == [-0.0, -0.0, -0.0]
        True
    rv   g      "@rc   g      ;@g      K@r   r_   r2   rB   g      ð¿g       Àr©   çUUUUUUÕ?N)r=   r`   r   ÚfloatÚroundÚepsilonDigitsr¦   ÚmaxÚminrP   r§   r¨   r   Úpow)rZ   r[   r�   rV   r¢   Za2Úa3ÚQÚRZR2ZQ3ZR2_Q3rL   ÚthetaZrQ2Za1_3r\   r]   Úx2r/   r/   r0   r   I  sT    &(
 





c                 C   s^   |\}}|\}}| \}}|| d }	|| d }
|| |	 }|| |
 }||f|	|
f||ffS )Nrc   r/   )r*   r+   r,   r¶   Úy2Úx3Úy3rm   rn   rk   rl   ri   rj   r/   r/   r0   rp   ª  s    rp   c                 C   s”   |\}}|\}}|\}}	| \}
}||
 d }|| d }|| d | }|| d | }||
 | | }|	| | | }||f||f||f|
|ffS ©Nrv   r/   )r*   r+   r,   r-   r¶   r·   r¸   r¹   Úx4Úy4rx   ry   rm   rn   rk   rl   ri   rj   r/   r/   r0   rz   µ  s    rz   )r*   r+   r,   r-   rZ   r[   r�   c                 C   s8   ||  d }|| d | }||  | | }|||| fS rº   r/   )r*   r+   r,   r-   r�   r[   rZ   r/   r/   r0   r†   Ã  s    r†   c                 C   sf   | \}}|\}}|\}}|}	|}
|d | }|d | }|| | }|| | }|	|
f||f||ffS r<   r/   )rZ   r[   r�   ri   rj   rk   rl   rm   rn   r]   Úy1r¶   r·   r¸   r¹   r/   r/   r0   r’   Õ  s    r’   c                 C   sœ   | \}}|\}}|\}}	|\}
}|
}|}|d |
 }|	d | }|| d | }||	 d | }||
 | | }|| |	 | }||f||f||f||ffS rº   r/   )rZ   r[   r�   rV   ri   rj   rk   rl   rm   rn   rx   ry   r]   r½   r¶   r·   r¸   r¹   r»   r¼   r/   r/   r0   rŸ   â  s    rŸ   ©rZ   r[   r�   rV   r5   r6   Zp4c                 C   s8   |d | }|| d | }| | | | }||||fS )Nr«   r/   r¾   r/   r/   r0   r¥   ò  s    r¥   c                 C   s8   | d d|  |d |  | d d|  |d |  fS )zÖFinds the point at time `t` on a line.

    Args:
        pt1, pt2: Coordinates of the line as 2D tuples.
        t: The time along the line.

    Returns:
        A 2D tuple with the coordinates of the point.
    r   rN   r/   )r*   r+   rg   r/   r/   r0   r"   	  s    
c                 C   sˆ   d| d|  | d  dd|  | |d   || |d   }d| d|  | d  dd|  | |d   || |d   }||fS )zèFinds the point at time `t` on a quadratic curve.

    Args:
        pt1, pt2, pt3: Coordinates of the curve as 2D tuples.
        t: The time along the curve.

    Returns:
        A 2D tuple with the coordinates of the point.
    rN   r   rM   r/   )r*   r+   r,   rg   rL   Úyr/   r/   r0   r     s    
@@c           
      C   s¨   || }d| }|| }|| | d  d|| |d  || |d     || |d   }|| | d  d|| |d  || |d     || |d   }	||	fS )zéFinds the point at time `t` on a cubic curve.

    Args:
        pt1, pt2, pt3, pt4: Coordinates of the curve as 2D tuples.
        t: The time along the curve.

    Returns:
        A 2D tuple with the coordinates of the point.
    rN   r   r1   r/   )
r*   r+   r,   r-   rg   r   r‹   rŒ   rL   r¿   r/   r/   r0   r    %  s     
"ÿþÿ"ÿþÿ)rg   r*   r+   r,   r-   )r   r‹   rŒ   c                 C   sL   || }d| }|| }|| |  d|| | || |    || |  S )zõFinds the point at time `t` on a cubic curve.

    Args:
        pt1, pt2, pt3, pt4: Coordinates of the curve as complex numbers.
        t: The time along the curve.

    Returns:
        A complex number with the coordinates of the point.
    rN   r1   r/   )r*   r+   r,   r-   rg   r   r‹   rŒ   r/   r/   r0   r!   ?  s    c                 C   sZ   t | ƒdkrt| |fžŽ S t | ƒdkr4t| |fžŽ S t | ƒdkrNt| |fžŽ S tdƒ‚d S ©NrM   r1   é   úUnknown curve degree)r‘   r"   r   r    Ú
ValueError)Úsegrg   r/   r/   r0   r#   X  s    c           	      C   sx   | \}}|\}}|\}}t || ƒtk r<t || ƒtk r<dS t || ƒt || ƒkrd|| ||  S || ||  S d S )Néÿÿÿÿrª   )	ÚsÚer	   ÚsxZsyÚexZeyZpxÚpyr/   r/   r0   Ú_line_t_of_ptg  s     rË   c                 C   sR   | d |d  |d |d   }| d |d  |d |d   }|dkoN|dk S )Nr   rN   r_   r/   )rZ   r[   ÚoriginZxDiffZyDiffr/   r/   r0   Ú'_both_points_are_on_same_side_of_originu  s      rÍ   c                 C   s  | \}}|\}}|\}}	|\}
}t  ||
¡rHt  ||¡rHt  ||¡sHg S t  |	|¡rpt  ||¡rpt  ||	¡spg S t  ||
¡rŒt  |	|¡rŒg S t  ||¡r¨t  ||¡r¨g S t  ||¡�r|}||	 |
|  }|||  |	 }||f}t|t| ||ƒt|||ƒd�gS t  ||
¡�r\|}|| ||  }|||  | }||f}t|t| ||ƒt|||ƒd�gS || ||  }||	 |
|  }t  ||¡�rŽg S || | ||  |	 ||  }|||  | }||f}t||| ƒ�rt|||ƒ�rt|t| ||ƒt|||ƒd�gS g S )aí  Finds intersections between two line segments.

    Args:
        s1, e1: Coordinates of the first line as 2D tuples.
        s2, e2: Coordinates of the second line as 2D tuples.

    Returns:
        A list of ``Intersection`` objects, each object having ``pt``, ``t1``
        and ``t2`` attributes containing the intersection point, time on first
        segment and time on second segment respectively.

    Examples::

        >>> a = lineLineIntersections( (310,389), (453, 222), (289, 251), (447, 367))
        >>> len(a)
        1
        >>> intersection = a[0]
        >>> intersection.pt
        (374.44882952482897, 313.73458370177315)
        >>> (intersection.t1, intersection.t2)
        (0.45069111555824465, 0.5408153767394238)
    ©r	   r
   r   )rO   Úiscloser   rË   rÍ   )Ús1Úe1Ús2Úe2Zs1xZs1yZe1xZe1yZs2xZs2yZe2xZe2yrL   Zslope34r¿   r	   Zslope12r/   r/   r0   r$   {  s‚    
ÿ
ÿ
ÿ
ÿ
ÿ
ÿ 
 
ÿÿ 
 
ÿÿ   ÿ
þ 
 
ÿÿc                 C   sT   | d }| d }t  |d |d  |d |d  ¡}t | ¡ |d  |d  ¡S )Nr   rÅ   rN   )rO   Úatan2r   ÚrotateÚ	translate)ÚsegmentÚstartÚendZangler/   r/   r0   Ú_alignment_transformationÉ  s    $rÚ   c                 C   s˜   t |ƒ | ¡}t| ƒdkrBt|Ž \}}}t|d |d |d ƒ}nDt| ƒdkr~t|Ž \}}}}t|d |d |d |d ƒ}ntdƒ‚tdd„ |D ƒƒS )Nr1   rN   rÁ   rÂ   c                 s   s*   | ]"}d |  krdkrn q|V  qdS )r_   rN   Nr/   ©rf   r”   r/   r/   r0   r~   Ý  s
      
  z._curve_line_intersections_t.<locals>.<genexpr>)	rÚ   ZtransformPointsr‘   rp   r   rz   r   rÃ   r   )ÚcurveÚlineZaligned_curverZ   r[   r�   ÚintersectionsrV   r/   r/   r0   Ú_curve_line_intersections_tÓ  s     rß   c                 C   s‚   t | ƒdkrt}nt | ƒdkr$t}ntdƒ‚g }t| |ƒD ]B}|| |fžŽ }t||fžŽ }t||fžŽ }| t|||d�¡ q:|S )aæ  Finds intersections between a curve and a line.

    Args:
        curve: List of coordinates of the curve segment as 2D tuples.
        line: List of coordinates of the line segment as 2D tuples.

    Returns:
        A list of ``Intersection`` objects, each object having ``pt``, ``t1``
        and ``t2`` attributes containing the intersection point, time on first
        segment and time on second segment respectively.

    Examples::
        >>> curve = [ (100, 240), (30, 60), (210, 230), (160, 30) ]
        >>> line  = [ (25, 260), (230, 20) ]
        >>> intersections = curveLineIntersections(curve, line)
        >>> len(intersections)
        3
        >>> intersections[0].pt
        (84.9000930760723, 189.87306176459828)
    r1   rÁ   rÂ   rÎ   )	r‘   r   r    rÃ   rß   rË   r"   rq   r   )rÜ   rÝ   ZpointFinderrÞ   rg   r	   Zline_tr/   r/   r0   r%   à  s    c                 C   s4   t | ƒdkrt| Ž S t | ƒdkr(t| Ž S tdƒ‚d S )Nr1   rÁ   rÂ   )r‘   r   r   rÃ   )r�   r/   r/   r0   Ú_curve_bounds  s
    rà   c                 C   sp   t | ƒdkr0| \}}t|||ƒ}||f||fgS t | ƒdkrJt| |fžŽ S t | ƒdkrdt| |fžŽ S tdƒ‚d S rÀ   )r‘   r"   r   r   rÃ   )r�   rg   rÆ   rÇ   Úmidpointr/   r/   r0   Ú_split_segment_at_t  s    râ   çü©ñÒMbP?c              	      sx  t | ƒ}t |ƒ}|sd}|s d}t||ƒ\}}|s6g S dd„ }	t|ƒˆ k rht|ƒˆ k rh|	|ƒ|	|ƒfgS t| dƒ\}
}|d |	|ƒf}|	|ƒ|d f}t|dƒ\}}|d |	|ƒf}|	|ƒ|d f}g }| t|
|ˆ ||d�¡ | t||ˆ ||d�¡ | t|
|ˆ ||d�¡ | t||ˆ ||d�¡ ‡ fdd	„}tƒ }g }|D ]0}||ƒ}||k�r\�qB| |¡ | |¡ �qB|S )
N)r_   rB   c                 S   s   d| d | d   S )Nr2   r   rN   r/   )Úrr/   r/   r0   rá   *  s    z._curve_curve_intersections_t.<locals>.midpointr2   r   rN   )Úrange1Úrange2c                    s    t | d ˆ  ƒt | d ˆ  ƒfS )Nr   rN   )Úint)r„   ©Ú	precisionr/   r0   Ú<lambda>O  ó    z._curve_curve_intersections_t.<locals>.<lambda>)	rà   r   r   râ   ÚextendÚ_curve_curve_intersections_tÚsetÚaddrq   )Úcurve1Úcurve2ré   rå   ræ   Zbounds1Zbounds2Z
intersectsÚ_rá   Zc11Zc12Z	c11_rangeZ	c12_rangeZc21Zc22Z	c21_rangeZ	c22_rangeÚfoundZ
unique_keyÚseenZunique_valuesr„   Úkeyr/   rè   r0   rí     s‚        ÿÿ    ÿÿ    ÿÿ    ÿÿ

rí   c                    s   t ˆ |ƒ}‡ fdd„|D ƒS )a  Finds intersections between a curve and a curve.

    Args:
        curve1: List of coordinates of the first curve segment as 2D tuples.
        curve2: List of coordinates of the second curve segment as 2D tuples.

    Returns:
        A list of ``Intersection`` objects, each object having ``pt``, ``t1``
        and ``t2`` attributes containing the intersection point, time on first
        segment and time on second segment respectively.

    Examples::
        >>> curve1 = [ (10,100), (90,30), (40,140), (220,220) ]
        >>> curve2 = [ (5,150), (180,20), (80,250), (210,190) ]
        >>> intersections = curveCurveIntersections(curve1, curve2)
        >>> len(intersections)
        3
        >>> intersections[0].pt
        (81.7831487395506, 109.88904552375288)
    c                    s,   g | ]$}t tˆ |d  ƒ|d  |d d�‘qS )r   rN   rÎ   )r   r#   )rf   r„   ©rð   r/   r0   ro   s  s   ÿz+curveCurveIntersections.<locals>.<listcomp>)rí   )rð   rñ   Zintersection_tsr/   rö   r0   r&   ]  s    

þc                 C   s–   d}t |ƒt | ƒkr"| | }} d}t | ƒdkrRt |ƒdkrFt| |ƒ}q€t| |ƒ}n.t | ƒdkrxt |ƒdkrxt| |žŽ }ntdƒ‚|sˆ|S dd„ |D ƒS )a)  Finds intersections between two segments.

    Args:
        seg1: List of coordinates of the first segment as 2D tuples.
        seg2: List of coordinates of the second segment as 2D tuples.

    Returns:
        A list of ``Intersection`` objects, each object having ``pt``, ``t1``
        and ``t2`` attributes containing the intersection point, time on first
        segment and time on second segment respectively.

    Examples::
        >>> curve1 = [ (10,100), (90,30), (40,140), (220,220) ]
        >>> curve2 = [ (5,150), (180,20), (80,250), (210,190) ]
        >>> intersections = segmentSegmentIntersections(curve1, curve2)
        >>> len(intersections)
        3
        >>> intersections[0].pt
        (81.7831487395506, 109.88904552375288)
        >>> curve3 = [ (100, 240), (30, 60), (210, 230), (160, 30) ]
        >>> line  = [ (25, 260), (230, 20) ]
        >>> intersections = segmentSegmentIntersections(curve3, line)
        >>> len(intersections)
        3
        >>> intersections[0].pt
        (84.9000930760723, 189.87306176459828)

    FTrM   z4Couldn't work out which intersection function to usec                 S   s    g | ]}t |j|j|jd �‘qS )rÎ   )r   r	   r   r
   rÛ   r/   r/   r0   ro   ¦  s     z/segmentSegmentIntersections.<locals>.<listcomp>)r‘   r&   r%   r$   rÃ   )Zseg1Zseg2ZswappedrÞ   r/   r/   r0   r'   y  s    
c                 C   sF   zt | ƒ}W n tk
r(   d|   Y S X dd dd„ |D ƒ¡ S dS )zw
    >>> _segmentrepr([1, [2, 3], [], [[2, [3, 4], [0.1, 2.2]]]])
    '(1, (2, 3), (), ((2, (3, 4), (0.1, 2.2))))'
    z%gz(%s)z, c                 s   s   | ]}t |ƒV  qd S rG   )Ú_segmentrepr)rf   rL   r/   r/   r0   r~   ³  s     z_segmentrepr.<locals>.<genexpr>N)ÚiterÚ	TypeErrorÚjoin)ÚobjÚitr/   r/   r0   r÷   ©  s
    r÷   c                 C   s   | D ]}t t|ƒƒ qdS )zlHelper for the doctests, displaying each segment in a list of
    segments on a single line as a tuple.
    N)Úprintr÷   )r“   r×   r/   r/   r0   ÚprintSegments¶  s    rþ   Ú__main__)r(   )r(   )rã   NN)VÚ__doc__ZfontTools.misc.arrayToolsr   r   r   ZfontTools.misc.transformr   rO   Úcollectionsr   r   ÚcompiledZCOMPILEDÚAttributeErrorÚImportErrorZfontTools.miscr   Ú__all__r   r8   ZreturnsÚdoubleÚlocalsr)   r>   r   r®   r`   ZcfuncÚinlinerJ   rR   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r€   rƒ   r‡   rP   r¦   r§   r¨   r   r   rp   rz   r†   r’   rŸ   r¥   r"   r   r    r!   r#   rË   rÍ   r$   rÚ   rß   r%   rà   râ   rí   r&   r'   r÷   rþ   Ú__name__ÚsysÚdoctestÚexitÚtestmodÚfailedr/   r/   r/   r0   Ú<module>   sè  

ä 
	
ü
üþ

#
ù	ù	 
ýý!"
üû$&9-%ø


ø
   ÿ#ó
!aù	ù	
ûN
&     ÿ
C0
