a
    —Æàgî¯  ã                   @   sl  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
W n" eefyf   ddlm
Z
 Y n0 e
jZdZe	dg d	¢ƒZg d
¢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d�e
je
je
jd�d‹dd„ƒƒƒZdZdZe
je
je
 e
j¡e
je
je
jd�dd„ ƒƒƒƒZe
je
je
 e
j¡e
je
jd�dd„ ƒƒƒƒ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d)�d*d+„ ƒƒƒZ$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e
je
jd0�d1d2„ ƒƒƒZ'd3d4„ Z(d5d6„ Z)d7d8„ Z*d9d:„ Z+d;d<„ Z,d=d>„ Z-e
je
je
je
je
je
je
je
je
jd?�d@dA„ ƒZ.e
 e
j¡e
je
je
je
je
je
je
je
je
jdB�e
je
je
je
je
jdC�dDdE„ ƒƒƒZ/dFdG„ Z0dHdI„ Z1e
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dJ�dKdL„ ƒZ2ddMlm3Z3m4Z4m5Z5m6Z6 e3fdNdO„Z7dPdQ„ Z8dRdS„ Z9dTdU„ Z:e
je
je
je
je
je
je
je
je
je
jdV�dWdX„ ƒƒƒZ;dYdZ„ Z<d[d\„ Z=e
je
je
je
je
je
je
je
je
je
jd]�d^d_„ ƒƒƒZ>d`da„ Z?dbdc„ Z@ddde„ ZAe
 e
j¡e
je
je
je
je
je
jdf�e
je
je
je
jdg�dhdi„ ƒƒƒZBdjdk„ ZCdldm„ ZDdndo„ ZEdpdq„ ZFdrds„ ZGdtdu„ ZHdvdw„ ZIdxdy„ ZJdzd{„ ZKdŒd}d~„ZLdd€„ ZMd�d‚„ ZNdƒd„„ ZOd…d†„ ZPd‡dˆ„ ZQeRd‰k�rhddlSZSddlTZTeS UeT V¡ jW¡ dS )�zNfontTools.misc.bezierTools.py -- tools for working with Bezier path segments.
é    )Ú
calcBoundsÚsectRectÚrectArea)ÚIdentityN)Ú
namedtuple)Úcythong•Ö&è.>Ú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© r0   úS/var/www/sistema_ama/venv/lib/python3.9/site-packages/fontTools/misc/bezierTools.pyr   8   s    ÿr   c                 C   s\   | d||   | d }|| | |  d }| | | d || |f||| || d |ffS )Né   g      À?ç      à?r0   )Úp0Úp1Úp2Úp3ZmidZderiv3r0   r0   r1   Ú_split_cubic_into_twoK   s
    þr8   )r4   r5   r6   r7   )ÚmultÚarchÚboxc           	      C   s‚   t || ƒ}t || ƒt || ƒ t || ƒ }||  t |krL|| d S t||||ƒ\}}t| g|¢R Ž t| g|¢R Ž  S d S ©Nr3   )ÚabsÚEPSILONr8   Ú_calcCubicArcLengthCRecurse)	r9   r4   r5   r6   r7   r:   r;   ZoneZtwor0   r0   r1   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   r0   r0   r1   r   h   s    r   é   g»½×Ùß|Û=©Úv1Úv2c                 C   s   | |  ¡  jS ©N)Ú	conjugateÚrealrC   r0   r0   r1   Ú_dot…   s    rI   ©Úxc                 C   s(   | t  | d d ¡ d t  | ¡d  S )Né   é   )ÚmathÚsqrtÚasinhrJ   r0   r0   r1   Ú_intSecAtan�   s    rQ   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-   r0   r0   r1   r   —   s     r   )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   rL   )r=   rI   ÚepsilonrQ   )r+   r,   r-   rS   rT   rU   rV   rW   rX   rY   rZ   r[   r\   r]   r0   r0   r1   r   º   s"     
(r   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*   rR   r0   r0   r1   r   í   s    r   rR   )Úv0rD   rE   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-   r`   rD   rE   r0   r0   r1   r   þ   s    !ÿÿr   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   rM   r0   ©Ú.0Út©ÚaxÚayÚbxÚbyÚcxÚcyr0   r1   Ú
<listcomp>D  s   þz'calcQuadraticBounds.<locals>.<listcomp>)ÚcalcQuadraticParametersÚappendr   )r+   r,   r-   Zax2Zay2ÚrootsÚpointsr0   rg   r1   r   *  s    þür   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*   r@   r0   r0   r1   r   L  s    ÿr   )r`   rD   rE   Ú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ãá?ra   )	r+   r,   r-   r.   r`   rD   rE   rs   rt   r0   r0   r1   r   j  s,    ÿþýÿÿþýÿr   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
    ç      @rb   c                 S   s(   g | ] }d |  krdk rn q|‘qS rc   r0   rd   r0   r0   r1   rn   ´  ó    z#calcCubicBounds.<locals>.<listcomp>c                 S   s(   g | ] }d |  krdk rn q|‘qS rc   r0   rd   r0   r0   r1   rn   µ  rv   c                    s\   g | ]T}ˆ | | | ˆ| |  ˆ|  ˆ ˆ| | | ˆ| |  ˆ|  ˆ f‘qS r0   r0   rd   ©rh   ri   rj   rk   rl   rm   ÚdxÚdyr0   r1   rn   ¸  s   ý&&þ)ÚcalcCubicParametersr   r   )r+   r,   r-   r.   Zax3Zay3Zbx2Zby2ZxRootsZyRootsrq   rr   r0   rw   r1   r   œ  s    &ûúr   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   rM   Nr0   )r+   r,   ÚwhereÚisHorizontalZpt1xZpt1yZpt2xZpt2yrh   ri   rj   rk   rY   rf   ZmidPtr0   r0   r1   r   Â  s    $
r   c           	      C   sd   t | ||ƒ\}}}t|| || || | ƒ}tdd„ |D ƒƒ}|sP| ||fgS t|||g|¢R Ž 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   rM   Nr0   rd   r0   r0   r1   Ú	<genexpr>"  rv   z!splitQuadratic.<locals>.<genexpr>)ro   r   ÚsortedÚ_splitQuadraticAtT)	r+   r,   r-   r{   r|   rY   rZ   ÚcÚ	solutionsr0   r0   r1   r   û  s    #ÿr   c                 C   sr   t | |||ƒ\}}}}	t|| || || |	| | ƒ}
tdd„ |
D ƒƒ}
|
s\| |||fgS t||||	g|
¢R Ž 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}   r0   rd   r0   r0   r1   r~   G  rv   zsplitCubic.<locals>.<genexpr>)rz   r   r   Ú_splitCubicAtT)r+   r,   r-   r.   r{   r|   rY   rZ   r�   rU   r‚   r0   r0   r1   r   (  s    ÿr   c                 G   s&   t | ||ƒ\}}}t|||g|¢R Ž 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))
    )ro   r€   )r+   r,   r-   ÚtsrY   rZ   r�   r0   r0   r1   r   M  s    r   c           
      G   sj   t | |||ƒ\}}}}t||||g|¢R Ž }	| g|	d dd… ¢R |	d< g |	d dd… ¢|‘R |	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 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))
    r   rM   Néÿÿÿÿ)rz   rƒ   )
r+   r,   r-   r.   r„   rY   rZ   r�   rU   Úsplitr0   r0   r1   r   e  s
    r   )r+   r,   r-   r.   rY   rZ   r�   rU   c           	      g   s6   t | |||ƒ\}}}}t||||g|¢R Ž 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Ú_splitCubicAtTC)	r+   r,   r-   r.   r„   rY   rZ   r�   rU   r0   r0   r1   r   „  s    r   )rf   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).
    rM   rL   r2   r0   )r+   r,   r-   r.   rf   r   rŒ   r�   rŽ   r‰   rŠ   r‹   r0   r0   r1   r   œ  s    2ÿr   c                 G   s  t |ƒ}g }| dd¡ | d¡ | \}}|\}}|\}	}
tt|ƒd ƒD ]¾}|| }||d  }|| }|| }|| }|| }d| | | | }d| | | | }|| }|| ||  |	 }|| ||  |
 }t||f||f||fƒ\}}}| |||f¡ qJ|S )Nr   r^   rA   rM   rL   )ÚlistÚinsertrp   ÚrangeÚlenÚcalcQuadraticPoints)rY   rZ   r�   r„   Úsegmentsrh   ri   rj   rk   rl   rm   Úir   r   ÚdeltaÚdelta_2Úa1xÚa1yÚb1xÚb1yÚt1_2Úc1xÚc1yr+   r,   r-   r0   r0   r1   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^   rA   rM   r2   rL   )r�   r�   rp   r‘   r’   ÚcalcCubicPoints)"rY   rZ   r�   rU   r„   r”   rh   ri   rj   rk   rl   rm   rx   ry   r•   r   r   r–   r—   Údelta_3rœ   Út1_3r˜   r™   rš   r›   r�   rž   Zd1xZd1yr+   r,   r-   r.   r0   r0   r1   rƒ   ß  s:    
  ÿrƒ   )rY   rZ   r�   rU   r   r   r–   r—   r¡   Úa1Úb1Úc1rT   c                 g   sð   t |ƒ}| dd¡ | d¡ tt|ƒd ƒD ]¼}|| }||d  }|| }|| }	||	 }
|| }|| }| |
 }d|  | | |	 }d| | | d|  |  | }| | ||  ||  | }t||||ƒ\}}}}||||fV  q.d S rŸ   )r�   r�   rp   r‘   r’   ÚcalcCubicPointsC)rY   rZ   r�   rU   r„   r•   r   r   r–   r—   r¡   rœ   r¢   r£   r¤   r¥   rT   r+   r,   r-   r.   r0   r0   r1   rˆ     s"    
 rˆ   )rO   Ú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^   rb   ©r=   r_   )rY   rZ   r�   rO   rq   ZDDZrDDr0   r0   r1   r   /  s    &r   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
    ru   g      "@rb   g      ;@g      K@r   r^   r3   rA   g      ð¿g       Àrª   çUUUUUUÕ?N)r=   r_   r   ÚfloatÚroundÚepsilonDigitsr§   ÚmaxÚminrO   r¨   r©   r   Úpow)rY   rZ   r�   rU   r£   Za2Úa3ÚQÚRZR2ZQ3ZR2_Q3rK   ÚthetaZrQ2Za1_3r[   r\   Úx2r0   r0   r1   r   P  sT    &(
 





r   c                 C   s^   |\}}|\}}| \}}|| d }	|| d }
|| |	 }|| |
 }||f|	|
f||ffS )Nrb   r0   )r+   r,   r-   r·   Úy2Úx3Úy3rl   rm   rj   rk   rh   ri   r0   r0   r1   ro   ±  s    ro   c                 C   s”   |\}}|\}}|\}}	| \}
}||
 d }|| d }|| d | }|| d | }||
 | | }|	| | | }||f||f||f|
|ffS ©Nru   r0   )r+   r,   r-   r.   r·   r¸   r¹   rº   Úx4Úy4rx   ry   rl   rm   rj   rk   rh   ri   r0   r0   r1   rz   ¼  s    rz   )r+   r,   r-   r.   rY   rZ   r�   c                 C   s8   ||  d }|| d | }||  | | }|||| fS r»   r0   )r+   r,   r-   r.   r�   rZ   rY   r0   r0   r1   r‡   Ê  s    r‡   c                 C   sf   | \}}|\}}|\}}|}	|}
|d | }|d | }|| | }|| | }|	|
f||f||ffS r<   r0   )rY   rZ   r�   rh   ri   rj   rk   rl   rm   r\   Úy1r·   r¸   r¹   rº   r0   r0   r1   r“   Ü  s    r“   c                 C   sœ   | \}}|\}}|\}}	|\}
}|
}|}|d |
 }|	d | }|| d | }||	 d | }||
 | | }|| |	 | }||f||f||f||ffS r»   r0   )rY   rZ   r�   rU   rh   ri   rj   rk   rl   rm   rx   ry   r\   r¾   r·   r¸   r¹   rº   r¼   r½   r0   r0   r1   r    é  s    r    ©rY   rZ   r�   rU   r6   r7   Zp4c                 C   s8   |d | }|| d | }| | | | }||||fS )Nr¬   r0   r¿   r0   r0   r1   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   rM   r0   )r+   r,   rf   r0   r0   r1   r#     s    
r#   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.
    rM   r   rL   r0   )r+   r,   r-   rf   rK   Úyr0   r0   r1   r      s    
@@r    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.
    rM   r   r2   r0   )
r+   r,   r-   r.   rf   r   rŒ   r�   rK   rÀ   r0   r0   r1   r!   ,  s     
"ÿþÿ"ÿþÿr!   )rf   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.
    rM   r2   r0   )r+   r,   r-   r.   rf   r   rŒ   r�   r0   r0   r1   r"   F  s    r"   c                 C   sf   t | ƒdkrtg | ¢|‘R Ž S t | ƒdkr<tg | ¢|‘R Ž S t | ƒdkrZtg | ¢|‘R Ž S tdƒ‚d S ©NrL   r2   é   úUnknown curve degree)r’   r#   r    r!   Ú
ValueError)Úsegrf   r0   r0   r1   r$   _  s    r$   c           	      C   sx   | \}}|\}}|\}}t || ƒtk r<t || ƒtk r<dS t || ƒt || ƒkrd|| ||  S || ||  S d S )Nr…   r«   )	ÚsÚer
   ZsxZsyÚexZeyZpxÚpyr0   r0   r1   Ú_line_t_of_ptn  s     rÊ   c                 C   sR   | d |d  |d |d   }| d |d  |d |d   }|dkoN|dk S )Nr   rM   r^   r0   )rY   rZ   ÚoriginZxDiffZyDiffr0   r0   r1   Ú'_both_points_are_on_same_side_of_origin|  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	   )rN   Úiscloser   rÊ   rÌ   )Ús1Úe1Ús2Úe2Zs1xZs1yZe1xZe1yZs2xZs2yZe2xZe2yrK   Zslope34rÀ   r
   Zslope12r0   r0   r1   r%   ‚  sr    
ÿ
ÿ
ÿ
ÿ
ÿ
ÿÿÿÿÿ ÿ
þÿÿr%   c                 C   sT   | d }| d }t  |d |d  |d |d  ¡}t | ¡ |d  |d  ¡S )Nr   r…   rM   )rN   Úatan2r   ÚrotateÚ	translate)ÚsegmentÚstartÚendZangler0   r0   r1   Ú_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 )Nr2   rM   rÂ   rÃ   c                 s   s*   | ]"}d |  krdkrn q|V  qdS )r^   rM   Nr0   ©re   r•   r0   r0   r1   r~   ä  rv   z._curve_line_intersections_t.<locals>.<genexpr>)	rØ   ÚtransformPointsr’   ro   r   rz   r   rÄ   r   )ÚcurveÚlineZaligned_curverY   rZ   r�   ÚintersectionsrU   r0   r0   r1   Ú_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 ]N}|g | ¢|‘R Ž }tg |¢|‘R Ž }tg |¢|‘R Ž }| 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)
    r2   rÂ   rÃ   r	   )	r’   r    r!   rÄ   rÞ   rÊ   r#   rp   r   )rÛ   rÜ   ZpointFinderrÝ   rf   r
   Zline_tr0   r0   r1   r&   ç  s    r&   c                 C   s4   t | ƒdkrt| Ž S t | ƒdkr(t| Ž S tdƒ‚d S )Nr2   rÂ   rÃ   )r’   r   r   rÄ   )r�   r0   r0   r1   Ú_curve_bounds  s
    rß   c                 C   sx   t | ƒdkr0| \}}t|||ƒ}||f||fgS t | ƒdkrNtg | ¢|‘R Ž S t | ƒdkrltg | ¢|‘R Ž S tdƒ‚d S rÁ   )r’   r#   r   r   rÄ   )r�   rf   rÆ   rÇ   Úmidpointr0   r0   r1   Ú_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}||ƒ}||v �r\�qB| |¡ | |¡ �qB|S )
N)r^   rA   c                 S   s   d| d | d   S )Nr3   r   rM   r0   )Úrr0   r0   r1   rà   1  s    z._curve_curve_intersections_t.<locals>.midpointr3   r   rM   )Úrange1Úrange2c                    s    t | d ˆ  ƒt | d ˆ  ƒfS )Nr   rM   )Úint)r„   ©Ú	precisionr0   r1   Ú<lambda>V  rv   z._curve_curve_intersections_t.<locals>.<lambda>)	rß   r   r   rá   ÚextendÚ_curve_curve_intersections_tÚsetÚaddrp   )Ú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„   Úkeyr0   rç   r1   rë   !  sb    
ÿÿ
ÿÿ
ÿÿ
ÿÿ

rë   c                 C   s    t | ƒ | ¡}tdd„ |D ƒƒS )Nc                 s   s   | ]}t  |d  d¡V  qdS )rM   r^   N)rN   rÍ   )re   Úpr0   r0   r1   r~   f  rv   z_is_linelike.<locals>.<genexpr>)rØ   rÚ   Úall)rÕ   Z	maybeliner0   r0   r1   Ú_is_lineliked  s    rö   c                    sŒ   t ˆ ƒrNˆ d ˆ d f}t |ƒrB|d |d f}tg |¢|¢R Ž S t||ƒS n"t |ƒrp|d |d f}tˆ |ƒ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)
    r   r…   c                    s,   g | ]$}t tˆ |d  ƒ|d  |d d�‘qS )r   rM   r	   )r   r$   )re   r„   ©rî   r0   r1   rn   Š  s   ÿz+curveCurveIntersections.<locals>.<listcomp>)rö   r%   r&   rë   )rî   rï   Zline1Zline2Zintersection_tsr0   r÷   r1   r'   i  s    


þr'   c                 C   sœ   d}t |ƒt | ƒkr"| | }} d}t | ƒdkrRt |ƒdkrFt| |ƒ}q†t| |ƒ}n4t | ƒdkr~t |ƒdkr~tg | ¢|¢R Ž }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)

    FTrL   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Ù   r0   r0   r1   rn   ½  rv   z/segmentSegmentIntersections.<locals>.<listcomp>)r’   r'   r&   r%   rÄ   )Zseg1Zseg2ZswappedrÝ   r0   r0   r1   r(   �  s    
r(   c                 C   sD   zt | ƒ}W n ty&   d|   Y S 0 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 rF   )Ú_segmentrepr)re   rK   r0   r0   r1   r~   Ê  rv   z_segmentrepr.<locals>.<genexpr>N)ÚiterÚ	TypeErrorÚjoin)ÚobjÚitr0   r0   r1   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Õ   r0   r0   r1   ÚprintSegmentsÍ  s    rÿ   Ú__main__)r)   )r)   )râ   NN)XÚ__doc__ZfontTools.misc.arrayToolsr   r   r   ZfontTools.misc.transformr   rN   Úcollectionsr   r   ÚAttributeErrorÚImportErrorZfontTools.miscZcompiledZCOMPILEDr>   r   Ú__all__r   r8   ÚreturnsÚdoubleÚlocalsr*   r?   r   r¯   r_   ZcfuncÚinlinerI   rQ   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r€   rƒ   rˆ   rO   r§   r¨   r©   r   r   ro   rz   r‡   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Úfailedr0   r0   r0   r1   Ú<module>   s¨   
	
ü
üþ

#
ù	ù	 
ýý!"
üû$&9-%ø

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