
    ljn                   :   U d Z ddlmZ g dZddlmZmZ ddlmZ ddl	m
Z
mZ ddlZddlmZ e
rdd	lmZmZmZmZmZmZmZmZmZmZmZmZmZ edgd            Zedhd            ZdidZdjdZdkdZ d  e!d          D             Z"de#d<   dld$Z$dmd%Z%dnd*Z&edod.            Z'edpd0            Z'edqd2            Z'edrd4            Z'dsd8Z'dtd:Z(edud;            Z)edvd<            Z)dwd=Z)edxd?            Z*edyd@            Z*edzdA            Z*d{dBZ*ed|dH            Z+ed}dI            Z+d~dJZ+ddNZ, ej-        dOg          a. ej-        dOg          a/ddPZ0 ej-        dQg          a1ddRZ2eddY            Z3edd[            Z3dd^Z3dd`Z4	 dddeZ5	 dddfZ6dS )u,   Utility functions related to Bézier curves.    )annotations)bezierpartial_bezier_pointssplit_beziersubdivide_bezierbezier_remapinterpolateinteger_interpolatemidinverse_interpolatematch_interpolate%get_smooth_cubic_bezier_handle_points	is_closed(proportions_along_bezier_curve_for_pointpoint_lies_on_bezier)CallableSequence)reduce)TYPE_CHECKINGoverloadN)choose)BezierPointsBezierPoints_ArrayBezierPointsLikeBezierPointsLike_Array	ColVectorMatrixMNPoint3DPoint3D_ArrayPoint3DLikePoint3DLike_ArrayQuadraticBezierPathQuadraticSplineSplinepointsr   return6Callable[[float | ColVector], Point3D | Point3D_Array]c                    d S N r%   s    M/home/agentuser/manim-venv/lib/python3.11/site-packages/manim/utils/bezier.pyr   r   4   s
     >AS    Sequence[Point3DLike_Array],Callable[[float | ColVector], Point3D_Array]c                    d S r)   r*   r+   s    r,   r   r   :   s	     473r-   'Point3D_Array | Sequence[Point3D_Array]c                    t          j        |           j        d         dz
  dk    rdfd}|S dk    rdfd}|S d	k    rdfd
}|S dk    rdfd}|S dfd}|S )u  Classic implementation of a Bézier curve.

    Parameters
    ----------
    points
        :math:`(d+1, 3)`-shaped array of :math:`d+1` control points defining a single Bézier
        curve of degree :math:`d`. Alternatively, for vectorization purposes, ``points`` can
        also be a :math:`(d+1, M, 3)`-shaped sequence of :math:`d+1` arrays of :math:`M`
        control points each, which define `M` Bézier curves instead.

    Returns
    -------
    bezier_func : :class:`typing.Callable` [[:class:`float` | :class:`~.ColVector`], :class:`~.Point3D` | :class:`~.Point3D_Array`]
        Function describing the Bézier curve. The behaviour of this function depends on
        the shape of ``points``:

            *   If ``points`` was a :math:`(d+1, 3)` array representing a single Bézier curve,
                then ``bezier_func`` can receive either:

                *   a :class:`float` ``t``, in which case it returns a
                    single :math:`(1, 3)`-shaped :class:`~.Point3D` representing the evaluation
                    of the Bézier at ``t``, or
                *   an :math:`(n, 1)`-shaped :class:`~.ColVector`
                    containing :math:`n` values to evaluate the Bézier curve at, returning instead
                    an :math:`(n, 3)`-shaped :class:`~.Point3D_Array` containing the points
                    resulting from evaluating the Bézier at each of the :math:`n` values.

                .. warning::
                    If passing a vector of :math:`t`-values to ``bezier_func``, it **must**
                    be a column vector/matrix of shape :math:`(n, 1)`. Passing an 1D array of
                    shape :math:`(n,)` is not supported and **will result in undefined behaviour**.

            *   If ``points`` was a :math:`(d+1, M, 3)` array describing :math:`M` Bézier curves,
                then ``bezier_func`` can receive either:

                *   a :class:`float` ``t``, in which case it returns an
                    :math:`(M, 3)`-shaped :class:`~.Point3D_Array` representing the evaluation
                    of the :math:`M` Bézier curves at the same value ``t``, or
                *   an :math:`(M, 1)`-shaped
                    :class:`~.ColVector` containing :math:`M` values, such that the :math:`i`-th
                    Bézier curve defined by ``points`` is evaluated at the corresponding :math:`i`-th
                    value in ``t``, returning again an :math:`(M, 3)`-shaped :class:`~.Point3D_Array`
                    containing those :math:`M` evaluations.

                .. warning::
                    Unlike the previous case, if you pass a :class:`~.ColVector` to ``bezier_func``,
                    it **must** contain exactly :math:`M` values, each value for each of the :math:`M`
                    Bézier curves defined by ``points``. Any array of shape other than :math:`(M, 1)`
                    **will result in undefined behaviour**.
    r      tfloat | ColVectorr&   Point3D | Point3D_Arrayc                >    t          j        |           d         z  S )Nr   )np	ones_liker4   Ps    r,   zero_bezierzbezier.<locals>.zero_bezierz   s    <??QqT))r-   c                >    d         | d         d         z
  z  z   S )Nr   r3   r*   r:   s    r,   linear_bezierzbezier.<locals>.linear_bezier   s#    Q4!qtad{+++r-      c                t    | | z  }d| z
  }||z  }|d         z  d| z  |z  d         z  z   |d         z  z   S )Nr3   r   r?   r*   )r4   t2mtmt2r;   s       r,   quadratic_bezierz bezier.<locals>.quadratic_bezier   sO    QBQBr'C1:A
QqT 11B1I==r-      c                    | | z  }|| z  }d| z
  }||z  }||z  }|d         z  d| z  |z  d         z  z   d|z  |z  d         z  z   |d         z  z   S )Nr3   r   rE   r?   r*   )r4   rA   t3rB   rC   mt3r;   s         r,   cubic_bezierzbezier.<locals>.cubic_bezier   sx    QBaBQBr'C(C1:Aad 22QVb[1Q45GG"qQRt)SSr-   c                   t          | t          j                   }|rt          j        dgj        R           }nat          | t          j                  sJ  | j        dgd j        D             R  } t          j        | j        d         gj        R           }|d d <   t                    D ]B}|d d d |z
  fxx         | |d d d|z
  dz   f         |d d d |z
  f         z
  z  z  cc<   C|r
|d         }|S |d d df         S )Nr3   c                    g | ]}d S )r3   r*   ).0dims     r,   
<listcomp>z4bezier.<locals>.nth_grade_bezier.<locals>.<listcomp>   s    555c555r-   r   r   r   )
isinstancer8   ndarrayemptyshapereshaperange)r4   	is_scalarBivalr;   degrees        r,   nth_grade_bezierz bezier.<locals>.nth_grade_bezier   sW   "1bj111	 	1!ag''AAa,,,,,	"655QW555666A!'!*/qw//00A!!!v 	V 	VA aaa6A:o!qA
Q,>)>'?!AAA|RS|OBT'T"UU  	T7CJAwr-   )r4   r5   r&   r6   )r8   asarrayrT   )r%   r<   r>   rD   rI   r\   r;   r[   s         @@r,   r   r   @   s   j 	
6AWQZ!^F{{	* 	* 	* 	* 	* 	* {{	, 	, 	, 	, 	, 	, {{	> 	> 	> 	> 	> 	>  {{	T 	T 	T 	T 	T 	T       , r-   afloatbr   c           
     b   |dk    r#t          j        |           }|d         |dd<   |S |dk    r#t          j        |           }|d         |dd<   |S t          j        |           } | j        d         dz
  }|dk    rd|z
  d|z
  }}||z  ||z  ||z  ||z  f\  }}}	}
||z  ||z  |	|z  |
|z  f\  }}}}t          j        |d|	z  |z  d|z  |z  |g|	|z  d|z  |z  |z  |	|z  z   ||z  d|z  |z  |z  z   ||z  g||
z  ||
z  d|z  |z  |z  z   d|z  |z  |z  ||z  z   ||z  g|d|
z  |z  d|z  |z  |gg          }|| z  S |dk    rVd|z
  d|z
  }}t          j        ||z  d|z  |z  ||z  g||z  ||z  ||z  z   ||z  g||z  d|z  |z  ||z  gg          }|| z  S |dk    r?| d         | d         z
  }t          j        | d         ||z  z   | d         ||z  z   g          S |dk    r| S t          j        | t                    }|j        d         }|dk    rGt          d|          D ]6}|d||z
  xx         ||d||z
  dz            |d||z
           z
  z  z  cc<   7|dk    rId|z
  d|z
  z  }t          d|          D ]-}||dxx         |||dz
  d         ||d         z
  z  z  cc<   .|S )uP  Given an array of ``points`` which define a Bézier curve, and two numbers :math:`a, b`
    such that :math:`0 \le a < b \le 1`, return an array of the same size, which describes the
    portion of the original Bézier curve on the interval :math:`[a, b]`.

    :func:`partial_bezier_points` is conceptually equivalent to calling :func:`split_bezier`
    twice and discarding unused Bézier curves, but this is more efficient and doesn't waste
    computations.

    .. seealso::
        See :func:`split_bezier` for an explanation on how to split Bézier curves.

    .. note::
        To find the portion of a Bézier curve with :math:`t` between :math:`a` and :math:`b`:

        1.  Split the curve at :math:`t = a` and extract its 2nd subcurve.
        2.  We cannot evaluate the new subcurve at :math:`t = b` because its range of values for :math:`t` is different.
            To find the correct value, we need to transform the interval :math:`[a, 1]` into :math:`[0, 1]`
            by first subtracting :math:`a` to get :math:`[0, 1-a]` and then dividing by :math:`1-a`. Thus, our new
            value must be :math:`t = \frac{b - a}{1 - a}`. Define :math:`u = \frac{b - a}{1 - a}`.
        3.  Split the subcurve at :math:`t = u` and extract its 1st subcurve.

        The final portion is a linear combination of points, and thus the process can be
        summarized as a linear transformation by some matrix in terms of :math:`a` and :math:`b`.
        This matrix is given explicitly for Bézier curves up to degree 3, which are often used in Manim.
        For higher degrees, the algorithm described previously is used.

        For the case of a quadratic Bézier curve:

        * Step 1:

        .. math::
            H'_1
            =
            \begin{pmatrix}
                (1-a)^2 & 2(1-a)a & a^2 \\
                0 & (1-a) & a \\
                0 & 0 & 1
            \end{pmatrix}
            \begin{pmatrix}
                p_0 \\
                p_1 \\
                p_2
            \end{pmatrix}

        * Step 2:

        .. math::
            H''_0
            &=
            \begin{pmatrix}
                1 & 0 & 0 \\
                (1-u) & u & 0\\
                (1-u)^2 & 2(1-u)u & u^2
            \end{pmatrix}
            H'_1
            \\
            &
            \\
            &=
            \begin{pmatrix}
                1 & 0 & 0 \\
                (1-u) & u & 0\\
                (1-u)^2 & 2(1-u)u & u^2
            \end{pmatrix}
            \begin{pmatrix}
                (1-a)^2 & 2(1-a)a & a^2 \\
                0 & (1-a) & a \\
                0 & 0 & 1
            \end{pmatrix}
            \begin{pmatrix}
                p_0 \\
                p_1 \\
                p_2
            \end{pmatrix}
            \\
            &
            \\
            &=
            \begin{pmatrix}
                (1-a)^2 & 2(1-a)a & a^2 \\
                (1-a)(1-b) & a(1-b) + (1-a)b & ab \\
                (1-b)^2 & 2(1-b)b & b^2
            \end{pmatrix}
            \begin{pmatrix}
                p_0 \\
                p_1 \\
                p_2
            \end{pmatrix}

        from where one can define a :math:`(3, 3)` matrix :math:`P_2` which, when applied over
        the array of ``points``, will return the desired partial quadratic Bézier curve:

        .. math::
            P_2
            =
            \begin{pmatrix}
                (1-a)^2 & 2(1-a)a & a^2 \\
                (1-a)(1-b) & a(1-b) + (1-a)b & ab \\
                (1-b)^2 & 2(1-b)b & b^2
            \end{pmatrix}

        Similarly, for the cubic Bézier curve case, one can define the following
        :math:`(4, 4)` matrix :math:`P_3`:

        .. math::
            P_3
            =
            \begin{pmatrix}
                (1-a)^3 & 3(1-a)^2a & 3(1-a)a^2 & a^3 \\
                (1-a)^2(1-b) & 2(1-a)a(1-b) + (1-a)^2b & a^2(1-b) + 2(1-a)ab & a^2b \\
                (1-a)(1-b)^2 & a(1-b)^2 + 2(1-a)(1-b)b & 2a(1-b)b + (1-a)b^2 & ab^2 \\
                (1-b)^3 & 3(1-b)^2b & 3(1-b)b^2 & b^3
            \end{pmatrix}

    Parameters
    ----------
    points
        set of points defining the bezier curve.
    a
        lower bound of the desired partial bezier curve.
    b
        upper bound of the desired partial bezier curve.

    Returns
    -------
    :class:`~.BezierPoints`
        An array containing the control points defining the partial Bézier curve.
    r3   rK   Nr   rE   r?   dtype)r8   arrayr]   rT   r_   rV   )r%   r^   r`   arrr[   mamba2b2ma2mb2a3b3ma3mb3portion_matrix	directionNrY   mus                       r,   r   r      s   D 	AvvhvRAAA
AvvhvQAAA
ZF\!_q F{{QABq5!a%b"r'9BS62638S2X=BSa#gk1r6B;3r1r6A:?S1W4b2gB
Q6NPRUVPVWc1s7QVb[1_4a!ebj1nrBw6NPQTVPVWa#gk1r6B;3	
 
 &&{{QABb!a%"*a!e,b!b&26/1q51b!a%"*a!e,
 
 &&{{1Iq	)	xq	A	M)q	A	M)
 
 	
 {{ (6
'
'
'C	!A 	Avvq! 	D 	DA !a%LLLAQQ]!3c'AE'l!BCCLLLL 	Avv!eAq! 	8 	8A GGGrSQ_s122w677GGGGJr-   r4   r$   c                   t          j        |           } | j        \  }}|dz
  }|dk    rnd|z
  }||z  }||z  }||z  }||z  }	d|z  |z  }
d|z  |z  }d|z  |z  }t          j        g d||ddg||
|dg||||	g||||	gd||
|gdd||gg dg          }|| z  S |dk    rFd|z
  }||z  }||z  }d|z  |z  }t          j        g d||dg|||g|||gd||gg dg          }|| z  S |dk    rA| d         || d         | d         z
  z  z   }t          j        | d         ||| d         g          S |dk    r"t          j        | d         | d         g          S t          j        d||f          }| |d<   | d         |d	<   t          d|          D ]I}|dd
||z
  fxx         ||dd||z
  dz   f         |dd
||z
  f         z
  z  z  cc<   |d         |d|f<   J|                    d|z  |          S )u  Split a Bézier curve at argument ``t`` into two curves.

    .. note::

        .. seealso::
            `A Primer on Bézier Curves #10: Splitting curves. Pomax. <https://pomax.github.io/bezierinfo/#splitting>`_

        As an example for a cubic Bézier curve, let :math:`p_0, p_1, p_2, p_3` be the points
        needed for the curve :math:`C_0 = [p_0, \ p_1, \ p_2, \ p_3]`.

        Define the 3 linear Béziers :math:`L_0, L_1, L_2` as interpolations of :math:`p_0, p_1, p_2, p_3`:

        .. math::
            L_0(t) &= p_0 + t(p_1 - p_0) \\
            L_1(t) &= p_1 + t(p_2 - p_1) \\
            L_2(t) &= p_2 + t(p_3 - p_2)

        Define the 2 quadratic Béziers :math:`Q_0, Q_1` as interpolations of :math:`L_0, L_1, L_2`:

        .. math::
            Q_0(t) &= L_0(t) + t(L_1(t) - L_0(t)) \\
            Q_1(t) &= L_1(t) + t(L_2(t) - L_1(t))

        Then :math:`C_0` is the following interpolation of :math:`Q_0` and :math:`Q_1`:

        .. math::
            C_0(t) = Q_0(t) + t(Q_1(t) - Q_0(t))

        Evaluating :math:`C_0` at a value :math:`t=t'` splits :math:`C_0` into two cubic Béziers :math:`H_0`
        and :math:`H_1`, defined by some of the points we calculated earlier:

        .. math::
            H_0 &= [p_0, &\ L_0(t'), &\ Q_0(t'), &\ C_0(t') &] \\
            H_1 &= [p_0(t'), &\ Q_1(t'), &\ L_2(t'), &\ p_3 &]

        As the resulting curves are obtained from linear combinations of ``points``, everything can
        be encoded into a matrix for efficiency, which is done for Bézier curves of degree up to 3.

        .. seealso::
            `A Primer on Bézier Curves #11: Splitting curves using matrices. Pomax. <https://pomax.github.io/bezierinfo/#matrixsplit>`_

        For the simpler case of a quadratic Bézier curve:

        .. math::
            H_0
            &=
            \begin{pmatrix}
                p_0 \\
                (1-t) p_0 + t p_1 \\
                (1-t)^2 p_0 + 2(1-t)t p_1 + t^2 p_2 \\
            \end{pmatrix}
            &=
            \begin{pmatrix}
                1 & 0 & 0 \\
                (1-t) & t & 0\\
                (1-t)^2 & 2(1-t)t & t^2
            \end{pmatrix}
            \begin{pmatrix}
                p_0 \\
                p_1 \\
                p_2
            \end{pmatrix}
            \\
            &
            \\
            H_1
            &=
            \begin{pmatrix}
                (1-t)^2 p_0 + 2(1-t)t p_1 + t^2 p_2 \\
                (1-t) p_1 + t p_2 \\
                p_2
            \end{pmatrix}
            &=
            \begin{pmatrix}
                (1-t)^2 & 2(1-t)t & t^2 \\
                0 & (1-t) & t \\
                0 & 0 & 1
            \end{pmatrix}
            \begin{pmatrix}
                p_0 \\
                p_1 \\
                p_2
            \end{pmatrix}

        from where one can define a :math:`(6, 3)` split matrix :math:`S_2` which can multiply
        the array of ``points`` to compute the return value:

        .. math::
            S_2
            &=
            \begin{pmatrix}
                1 & 0 & 0 \\
                (1-t) & t & 0 \\
                (1-t)^2 & 2(1-t)t & t^2 \\
                (1-t)^2 & 2(1-t)t & t^2 \\
                0 & (1-t) & t \\
                0 & 0 & 1
            \end{pmatrix}
            \\
            &
            \\
            S_2 P
            &=
            \begin{pmatrix}
                1 & 0 & 0 \\
                (1-t) & t & 0 \\
                (1-t)^2 & 2(1-t)t & t^2 \\
                (1-t)^2 & 2(1-t)t & t^2 \\
                0 & (1-t) & t \\
                0 & 0 & 1
            \end{pmatrix}
            \begin{pmatrix}
                p_0 \\
                p_1 \\
                p_2
            \end{pmatrix}
            =
            \begin{pmatrix}
                \vert \\
                H_0 \\
                \vert \\
                \vert \\
                H_1 \\
                \vert
            \end{pmatrix}

        For the previous example with a cubic Bézier curve:

        .. math::
            H_0
            &=
            \begin{pmatrix}
                p_0 \\
                (1-t) p_0 + t p_1 \\
                (1-t)^2 p_0 + 2(1-t)t p_1 + t^2 p_2 \\
                (1-t)^3 p_0 + 3(1-t)^2 t p_1 + 3(1-t)t^2 p_2 + t^3 p_3
            \end{pmatrix}
            &=
            \begin{pmatrix}
                1 & 0 & 0 & 0 \\
                (1-t) & t & 0 & 0 \\
                (1-t)^2 & 2(1-t)t & t^2 & 0 \\
                (1-t)^3 & 3(1-t)^2 t & 3(1-t)t^2 & t^3
            \end{pmatrix}
            \begin{pmatrix}
                p_0 \\
                p_1 \\
                p_2 \\
                p_3
            \end{pmatrix}
            \\
            &
            \\
            H_1
            &=
            \begin{pmatrix}
                (1-t)^3 p_0 + 3(1-t)^2 t p_1 + 3(1-t)t^2 p_2 + t^3 p_3 \\
                (1-t)^2 p_1 + 2(1-t)t p_2 + t^2 p_3 \\
                (1-t) p_2 + t p_3 \\
                p_3
            \end{pmatrix}
            &=
            \begin{pmatrix}
                (1-t)^3 & 3(1-t)^2 t & 3(1-t)t^2 & t^3 \\
                0 & (1-t)^2 & 2(1-t)t & t^2 \\
                0 & 0 & (1-t) & t \\
                0 & 0 & 0 & 1
            \end{pmatrix}
            \begin{pmatrix}
                p_0 \\
                p_1 \\
                p_2 \\
                p_3
            \end{pmatrix}

        from where one can define a :math:`(8, 4)` split matrix :math:`S_3` which can multiply
        the array of ``points`` to compute the return value:

        .. math::
            S_3
            &=
            \begin{pmatrix}
                1 & 0 & 0 & 0 \\
                (1-t) & t & 0 & 0 \\
                (1-t)^2 & 2(1-t)t & t^2 & 0 \\
                (1-t)^3 & 3(1-t)^2 t & 3(1-t)t^2 & t^3 \\
                (1-t)^3 & 3(1-t)^2 t & 3(1-t)t^2 & t^3 \\
                0 & (1-t)^2 & 2(1-t)t & t^2 \\
                0 & 0 & (1-t) & t \\
                0 & 0 & 0 & 1
            \end{pmatrix}
            \\
            &
            \\
            S_3 P
            &=
            \begin{pmatrix}
                1 & 0 & 0 & 0 \\
                (1-t) & t & 0 & 0 \\
                (1-t)^2 & 2(1-t)t & t^2 & 0 \\
                (1-t)^3 & 3(1-t)^2 t & 3(1-t)t^2 & t^3 \\
                (1-t)^3 & 3(1-t)^2 t & 3(1-t)t^2 & t^3 \\
                0 & (1-t)^2 & 2(1-t)t & t^2 \\
                0 & 0 & (1-t) & t \\
                0 & 0 & 0 & 1
            \end{pmatrix}
            \begin{pmatrix}
                p_0 \\
                p_1 \\
                p_2 \\
                p_3
            \end{pmatrix}
            =
            \begin{pmatrix}
                \vert \\
                H_0 \\
                \vert \\
                \vert \\
                H_1 \\
                \vert
            \end{pmatrix}

    Parameters
    ----------
    points
        The control points of the Bézier curve.

    t
        The ``t``-value at which to split the Bézier curve.

    Returns
    -------
    :class:`~.Point3D_Array`
        An array containing the control points defining the two Bézier curves.
    r3   rE   r?   )r3   r   r   r   r   )r   r   r   r3   )r3   r   r   )r   r   r3   rP   N)r3   r   )r8   r]   rT   rd   rS   rV   rU   )r%   r4   rr   rN   r[   rB   rC   rH   rA   rG   two_mt_tthree_mt2_tthree_mt_t2split_matrixtwo_tmtmiddlere   rY   s                     r,   r   r     s   X ZF\FAsUF{{U2gBhU!Vr6A:#gk"frk xQ1hA&k;3k;3C2&Ar1	
 
 f$${{U2gUa%"* x		Q
gr"gr"B
			
 	
 f$${{Q&)fQi"788xFFF1I>???{{xF1I./// (Aq#;

CCFq	CI
 1a[[   	AwQwJ1Aq1q519}$4 5AwQwJ GHH IAqD		;;q1uc"""r-   c                    g | ]}i S r*   r*   )rM   rY   s     r,   rO   rO     s    2H2H2H!22H2H2Hr-      zlist[dict[int, MatrixMN]]SUBDIVISION_MATRICESn_pointsintn_divisionsr   c           
        | dvrt          d          t          | dz
                               |d          }||S t          j        | |z  | f          }| dk    rt          |          D ]}||z  }||z  }|dz   }||z  }||z  }||z
  }	|	|	z  }
|
|	z  }|	dz
  }||z  }||z  }t          j        |d|
z  |z  d|	z  |z  |g|
|z  d|	z  |z  |z  |
|z  z   ||z  d|	z  |z  |z  z   ||z  g|	|z  ||z  d|	z  |z  |z  z   d|z  |z  |z  |	|z  z   ||z  g|d|z  |z  d|z  |z  |gg          |d|z  d|dz   z  <   |||z  |z  z  }n| dk    rt          |          D ]f}|dz   }||z
  }	|	dz
  }t          j        |	|	z  d|z  |	z  ||z  g|	|z  ||z  ||	z  z   ||z  g||z  d|z  |z  ||z  gg          |d|z  d|dz   z  <   g|||z  z  }nh| dk    rUt          j        |dz             }|dd         |ddddf<   |dd         |ddddf<   |ddddf         |ddd	f<   ||z  }n| dk    rd|dd<   |t          | dz
           |<   |S )
u  Gets the matrix which subdivides a Bézier curve of
    ``n_points`` control points into ``n_divisions`` parts.

    Auxiliary function for :func:`subdivide_bezier`. See its
    docstrings for an explanation of the matrix build process.

    Parameters
    ----------
    n_points
        The number of control points of the Bézier curve to
        subdivide. This function only handles up to 4 points.
    n_divisions
        The number of parts to subdivide the Bézier curve into.

    Returns
    -------
    MatrixMN
        The matrix which, upon multiplying the control points of the
        Bézier curve, subdivides it into ``n_divisions`` parts.
    )r3   r?   rE   r|   u_   This function does not support subdividing Bézier curves with 0 or more than 4 control points.r3   Nr|   rE   r?   rK   r   )NotImplementedErrorr}   getr8   rS   rV   rd   arange)r~   r   subdivision_matrixrY   i2i3ip1ip12ip13nminmi2nmi3nmim1nmim12nmim13	aux_ranges                   r,   _get_subdivision_matrixr     s   * |##!;
 
 	

 .hl;??TRR%!!8k#98"DEE 1}}{## (	 (	AQBaBa%C9D#:D/C9D#:D!GEU]Fe^F68h D1C"	 uC%!+dSj8
QWq[3%66S	 f
QWu_s%::E	A+cDj8D	 F
S(E	D(	'7 7q1uqAE{2338 	kK7+EE 
Q{## 
	 
	Aa%C/C!GE68h3YAQU35[!e)cCi"7SAU]AGeOS3Y?7 7q1uqAE{233 	kK77 
QIkAo..	%.ss^33Q36"&/m14a47##5dddAg#>111a4 k) 
Q !1116HA&{3r-   c                   t          j        |           } |dk    r| S | j        \  }}|dk    rt          ||          }|| z  S t          j        |||f          }| |d<   t          |dz
  dd          D ]}||         }||dz
           }|d         |d<   ||z
  ||z
  dz   z  }	t          d|          D ]A}
|d||
z
  xx         |	|d||
z
  dz            |d||
z
           z
  z  z  cc<   |d         ||
<   B|                    ||z  |          S )u  Subdivide a Bézier curve into :math:`n` subcurves which have the same shape.

    The points at which the curve is split are located at the
    arguments :math:`t = \frac{i}{n}`, for :math:`i \in \{1, ..., n-1\}`.

    .. seealso::

        * See :func:`split_bezier` for an explanation on how to split Bézier curves.
        * See :func:`partial_bezier_points` for an extra understanding of this function.


    .. note::
        The resulting subcurves can be expressed as linear combinations of
        ``points``, which can be encoded in a single matrix that is precalculated
        for 2nd and 3rd degree Bézier curves.

        As an example for a quadratic Bézier curve: taking inspiration from the
        explanation in :func:`partial_bezier_points`, where the following matrix
        :math:`P_2` was defined to extract the portion of a quadratic Bézier
        curve for :math:`t \in [a, b]`:

        .. math::
            P_2
            =
            \begin{pmatrix}
                (1-a)^2 & 2(1-a)a & a^2 \\
                (1-a)(1-b) & a(1-b) + (1-a)b & ab \\
                (1-b)^2 & 2(1-b)b & b^2
            \end{pmatrix}

        the plan is to replace :math:`[a, b]` with
        :math:`\left[ \frac{i-1}{n}, \frac{i}{n} \right], \ \forall i \in \{1, ..., n\}`.

        As an example for :math:`n = 2` divisions, construct :math:`P_1` for
        the interval :math:`\left[ 0, \frac{1}{2} \right]`, and :math:`P_2` for the
        interval :math:`\left[ \frac{1}{2}, 1 \right]`:

        .. math::
            P_1
            =
            \begin{pmatrix}
                1 & 0 & 0 \\
                0.5 & 0.5 & 0 \\
                0.25 & 0.5 & 0.25
            \end{pmatrix}
            ,
            \quad
            P_2
            =
            \begin{pmatrix}
                0.25 & 0.5 & 0.25 \\
                0 & 0.5 & 0.5 \\
                0 & 0 & 1
            \end{pmatrix}

        Therefore, the following :math:`(6, 3)` subdivision matrix :math:`D_2` can be
        constructed, which will subdivide an array of ``points`` into 2 parts:

        .. math::
            D_2
            =
            \begin{pmatrix}
                M_1 \\
                M_2
            \end{pmatrix}
            =
            \begin{pmatrix}
                1 & 0 & 0 \\
                0.5 & 0.5 & 0 \\
                0.25 & 0.5 & 0.25 \\
                0.25 & 0.5 & 0.25 \\
                0 & 0.5 & 0.5 \\
                0 & 0 & 1
            \end{pmatrix}

        For quadratic and cubic Bézier curves, the subdivision matrices are memoized for
        efficiency. For higher degree curves, an iterative algorithm inspired by the
        one from :func:`split_bezier` is used instead.

    .. image:: /_static/bezier_subdivision_example.png

    Parameters
    ----------
    points
        The control points of the Bézier curve.

    n_divisions
        The number of curves to subdivide the Bézier curve into

    Returns
    -------
    :class:`~.Spline`
        An array containing the points defining the new :math:`n` subcurves.
    r3   r|   rK   r   N)r8   r]   rT   r   rS   rV   rU   )r%   r   rr   rN   r   beziers	curve_numcurrprevr^   rY   s              r,   r   r   9  sa   ~ ZFa\FAsAvv4QDD!F** hQ,--GGBK;?Ar22  	y!y1}%q'Q9$y)@1)DE q! 	 	A 1q5MMMQ$q1q519}"5Wq1uW"EFFMMM 1gDGG	 ??;?C000r-   bezier_tuplesr   new_number_of_curvesr   c                   t          j        |           } | j        \  }}}t          j        |d          |z  |z  }t          j        |d          }t           j                            ||d           t          j        |||f          }d}t          | |d          D ]7\  }	}
t          |	|
          
                    |
||          ||||
z   <   ||
z  }8|S )u  Subdivides each curve in ``bezier_tuples`` into as many parts as necessary, until the final number of
    curves reaches a desired amount, ``new_number_of_curves``.

    Parameters
    ----------
    bezier_tuples
        An array of multiple Bézier curves of degree :math:`d` to be remapped. The shape of this array
        must be ``(current_number_of_curves, nppc, dim)``, where:

        *   ``current_number_of_curves`` is the current amount of curves in the array ``bezier_tuples``,
        *   ``nppc`` is the amount of points per curve, such that their degree is ``nppc-1``, and
        *   ``dim`` is the dimension of the points, usually :math:`3`.

    new_number_of_curves
        The number of curves that the output will contain. This needs to be higher than the current number.

    Returns
    -------
    :class:`~.BezierPoints_Array`
        The new array of shape ``(new_number_of_curves, nppc, dim)``,
        containing the new Bézier curves after the remap.
    rY   rb   r3   r   T)strict)r8   r]   rT   r   zerosaddatrS   zipr   rU   )r   r   current_number_of_curvesnppcrN   repeat_indicessplit_factors
new_tuplesindexcurvesfs              r,   r   r     s    4 J}--M*7*='dC 		&c2225MM	N H5SAAAMFIIm^Q////s;<<JEdCCC  	r)9%)D)D)L)Lc*
 *

552:%& 	r-   startendalphac                    d S r)   r*   r   r   r   s      r,   r	   r	     s    BE#r-   r   c                    d S r)   r*   r   s      r,   r	   r	         JM#r-   r   c                    d S r)   r*   r   s      r,   r	   r	      s    HKr-   r   c                    d S r)   r*   r   s      r,   r	   r	         RURUr-   float | Point3Dr5   +float | ColVector | Point3D | Point3D_Arrayc                    d|z
  | z  ||z  z   S )a  Linearly interpolates between two values ``start`` and ``end``.

    Parameters
    ----------
    start
        The start of the range.
    end
        The end of the range.
    alpha
        A float between 0 and 1, or an :math:`(n, 1)` column vector containing
        :math:`n` floats between 0 and 1 to interpolate in a vectorized fashion.

    Returns
    -------
    :class:`float` | :class:`~.ColVector` | :class:`~.Point3D` | :class:`~.Point3D_Array`
        The result of the linear interpolation.

        *   If ``start`` and ``end`` are of type :class:`float`, and:

            * ``alpha`` is also a :class:`float`, the return is simply another :class:`float`.
            * ``alpha`` is a :class:`~.ColVector`, the return is another :class:`~.ColVector`.

        *   If ``start`` and ``end`` are of type :class:`~.Point3D`, and:

            * ``alpha`` is a :class:`float`, the return is another :class:`~.Point3D`.
            * ``alpha`` is a :class:`~.ColVector`, the return is a :class:`~.Point3D_Array`.
    r3   r*   r   s      r,   r	   r	     s    @ I,,r-   tuple[int, float]c                    |dk    rt          |dz
            dfS |dk    rt          |           dfS t          t          | ||                    }|| z
  |z  dz  }||fS )a  
    This is a variant of interpolate that returns an integer and the residual

    Parameters
    ----------
    start
        The start of the range
    end
        The end of the range
    alpha
        a float between 0 and 1.

    Returns
    -------
    tuple[int, float]
        This returns an integer between start and end (inclusive) representing
        appropriate interpolation between them, along with a
        "residue" representing a new proportion between the
        returned integer and the next one of the
        list.

    Example
    -------

    .. code-block:: pycon

        >>> integer, residue = integer_interpolate(start=0, end=10, alpha=0.46)
        >>> np.allclose((integer, residue), (4, 0.6))
        True
    r3   g      ?r   )r   r	   )r   r   r   valueresidues        r,   r
   r
   +  ss    F zzC!Gc""zzE

AE3..//Eeu$)G7r-   c                    d S r)   r*   r   r   s     r,   r   r   W  s    ,/Cr-   c                    d S r)   r*   r   s     r,   r   r   [  s    25#r-   c                    | |z   dz  S )zReturns the midpoint between two values.

    Parameters
    ----------
    start
        The first value
    end
        The second value

    Returns
    -------
        The midpoint between the two values
    g       @r*   r   s     r,   r   r   _  s     CK3r-   r   c                    d S r)   r*   r   r   r   s      r,   r   r   p  r   r-   c                    d S r)   r*   r   s      r,   r   r   t  s    NQcr-   c                    d S r)   r*   r   s      r,   r   r   x  r   r-   c                8    t          j        || z
  || z
            S )au  Perform inverse interpolation to determine the alpha
    values that would produce the specified ``value``
    given the ``start`` and ``end`` values or points.

    Parameters
    ----------
    start
        The start value or point of the interpolation.
    end
        The end value or point of the interpolation.
    value
        The value or point for which the alpha value
        should be determined.

    Returns
    -------
        The alpha values producing the given input
        when interpolating between ``start`` and ``end``.

    Example
    -------

    .. code-block:: pycon

        >>> inverse_interpolate(start=2, end=6, value=4)
        np.float64(0.5)

        >>> start = np.array([1, 2, 1])
        >>> end = np.array([7, 8, 11])
        >>> value = np.array([4, 5, 5])
        >>> inverse_interpolate(start, end, value)
        array([0.5, 0.5, 0.4])
    )r8   true_divider   s      r,   r   r   |  s    L >%%-u555r-   	new_startnew_end	old_startold_end	old_valuec                    d S r)   r*   r   r   r   r   r   s        r,   r   r     s	     Cr-   c                    d S r)   r*   r   s        r,   r   r     s	     cr-   c                F    t          |||          }t          | ||          S )a  Interpolate a value from an old range to a new range.

    Parameters
    ----------
    new_start
        The start of the new range.
    new_end
        The end of the new range.
    old_start
        The start of the old range.
    old_end
        The end of the old range.
    old_value
        The value within the old range whose corresponding
        value in the new range (with the same alpha value)
        is desired.

    Returns
    -------
        The interpolated value within the new range.

    Examples
    --------
    >>> from manim import match_interpolate
    >>> match_interpolate(0, 100, 10, 20, 15)
    np.float64(50.0)
    )r   r	   )r   r   r   r   r   	old_alphas         r,   r   r     s1    D $Iw	BBI  r-   anchorsr!   #tuple[Point3D_Array, Point3D_Array]c                   t          j        |           } | j        d         }|dk    r9| j        d         }t          j        d|f          t          j        d|f          fS |dk    rCt	          | d         | d         t          j        dgdgg                    }|d         |d         fS t          |           }|rt          |           S t          |           S )u  Given an array of anchors for a cubic spline (array of connected cubic
    Bézier curves), compute the 1st and 2nd handle for every curve, so that
    the resulting spline is smooth.

    Parameters
    ----------
    anchors
        Anchors of a cubic spline.

    Returns
    -------
    :class:`tuple` [:class:`~.Point3D_Array`, :class:`~.Point3D_Array`]
        A tuple of two arrays: one containing the 1st handle for every curve in
        the cubic spline, and the other containing the 2nd handles.
    r   r3   r?   UUUUUU?gUUUUUU?)	r8   r]   rT   r   r	   rd   r   ,get_smooth_closed_cubic_bezier_handle_points*get_smooth_open_cubic_bezier_handle_points)r   	n_anchorsrN   rZ   curve_is_closeds        r,   r   r     s    $ j!!Ga I A~~mAxC!!28QH#5#555
 A~~'!*gaj"(UGeW;M2N2NOOAA  ((O C;GDDD9'BBBr-   r   c                   t          j        |           }|j        d         dz
  }|j        d         }t          j        }||dz
  k     rt          j        |dz
            }t          j        |dz
            }t          |d|<   t          |d|<   t          ||dz
            D ].}dd||dz
           z
  z  ||<   ||          ||dz
           z  ||<   /|a|an$t          d|dz
           }t          d|dz
           }dd||dz
           z
  z  }|d||dz
           z
  z  }	t          j        ||f          }
|	|
|dz
  <   t          |dz
  dd          D ]"}||         ||         |
|dz            z  z
  |
|<   #t          j        ||f          }d|d|         z  d|dd         z  z   }|d         dz  |d<   t          d|dz
            D ]"}||         ||         ||dz
           z
  z  ||<   #|||dz
           ||dz
           z
  z  ||dz
  <   |}t          |dz
  dd          D ]"}||         ||         ||dz            z  z
  ||<   #|dd|
d         z   |
|dz
           z   z  |
z  |d         ||dz
           z   z  z
  }t          j        ||f          }d|d|         z  |d|         z
  |d|dz
  <   d||         z  |d         z
  ||dz
  <   ||fS )u!  Special case of :func:`get_smooth_cubic_bezier_handle_points`,
    when the ``anchors`` form a closed loop.

    .. note::
        A system of equations must be solved to get the first handles of
        every Bézier curve (referred to as :math:`H_1`).
        Then :math:`H_2` (the second handles) can be obtained separately.

        .. seealso::
            The equations were obtained from:

            * `Conditions on control points for continuous curvature. (2016). Jaco Stuifbergen. <http://www.jacos.nl/jacos_html/spline/theory/theory_2.html>`_

        In general, if there are :math:`N+1` anchors, there will be :math:`N` Bézier curves
        and thus :math:`N` pairs of handles to find. We must solve the following
        system of equations for the 1st handles (example for :math:`N = 5`):

        .. math::
            \begin{pmatrix}
                4 & 1 & 0 & 0 & 1 \\
                1 & 4 & 1 & 0 & 0 \\
                0 & 1 & 4 & 1 & 0 \\
                0 & 0 & 1 & 4 & 1 \\
                1 & 0 & 0 & 1 & 4
            \end{pmatrix}
            \begin{pmatrix}
                H_{1,0} \\
                H_{1,1} \\
                H_{1,2} \\
                H_{1,3} \\
                H_{1,4}
            \end{pmatrix}
            =
            \begin{pmatrix}
                4A_0 + 2A_1 \\
                4A_1 + 2A_2 \\
                4A_2 + 2A_3 \\
                4A_3 + 2A_4 \\
                4A_4 + 2A_5
            \end{pmatrix}

        which will be expressed as :math:`RH_1 = D`.

        :math:`R` is almost a tridiagonal matrix, so we could use Thomas' algorithm.

        .. seealso::
            `Tridiagonal matrix algorithm. Wikipedia. <https://en.wikipedia.org/wiki/Tridiagonal_matrix_algorithm>`_

        However, :math:`R` has ones at the opposite corners. A solution to this is
        the first decomposition proposed in the link below, with :math:`\alpha = 1`:

        .. seealso::
            `Tridiagonal matrix algorithm # Variants. Wikipedia. <https://en.wikipedia.org/wiki/Tridiagonal_matrix_algorithm#Variants>`_

        .. math::
            R
            =
            \begin{pmatrix}
                4 & 1 & 0 & 0 & 1 \\
                1 & 4 & 1 & 0 & 0 \\
                0 & 1 & 4 & 1 & 0 \\
                0 & 0 & 1 & 4 & 1 \\
                1 & 0 & 0 & 1 & 4
            \end{pmatrix}
            &=
            \begin{pmatrix}
                3 & 1 & 0 & 0 & 0 \\
                1 & 4 & 1 & 0 & 0 \\
                0 & 1 & 4 & 1 & 0 \\
                0 & 0 & 1 & 4 & 1 \\
                0 & 0 & 0 & 1 & 3
            \end{pmatrix}
            +
            \begin{pmatrix}
                1 & 0 & 0 & 0 & 1 \\
                0 & 0 & 0 & 0 & 0 \\
                0 & 0 & 0 & 0 & 0 \\
                0 & 0 & 0 & 0 & 0 \\
                1 & 0 & 0 & 0 & 1
            \end{pmatrix}
            \\
            &
            \\
            &=
            \begin{pmatrix}
                3 & 1 & 0 & 0 & 0 \\
                1 & 4 & 1 & 0 & 0 \\
                0 & 1 & 4 & 1 & 0 \\
                0 & 0 & 1 & 4 & 1 \\
                0 & 0 & 0 & 1 & 3
            \end{pmatrix}
            +
            \begin{pmatrix}
                1 \\
                0 \\
                0 \\
                0 \\
                1
            \end{pmatrix}
            \begin{pmatrix}
                1 & 0 & 0 & 0 & 1
            \end{pmatrix}
            \\
            &
            \\
            &=
            T + uv^t

        We decompose :math:`R = T + uv^t`, where :math:`T` is a tridiagonal matrix, and
        :math:`u, v` are :math:`N`-D vectors such that :math:`u_0 = u_{N-1} = v_0 = v_{N-1} = 1`,
        and :math:`u_i = v_i = 0, \forall i \in \{1, ..., N-2\}`.

        Thus:

        .. math::
            RH_1 &= D \\
            \Rightarrow (T + uv^t)H_1 &= D

        If we find a vector :math:`q` such that :math:`Tq = u`:

        .. math::
            \Rightarrow (T + Tqv^t)H_1 &= D \\
            \Rightarrow T(I + qv^t)H_1 &= D \\
            \Rightarrow H_1 &= (I + qv^t)^{-1} T^{-1} D

        According to Sherman-Morrison's formula:

        .. seealso::
            `Sherman-Morrison's formula. Wikipedia. <https://en.wikipedia.org/wiki/Sherman%E2%80%93Morrison_formula>`_

        .. math::
            (I + qv^t)^{-1} = I - \frac{1}{1 + v^tq} qv^t

        If we find :math:`Y = T^{-1} D`, or in other words, if we solve for
        :math:`Y` in :math:`TY = D`:

        .. math::
            H_1 &= (I + qv^t)^{-1} T^{-1} D \\
            &= (I + qv^t)^{-1} Y \\
            &= (I - \frac{1}{1 + v^tq} qv^t) Y \\
            &= Y - \frac{1}{1 + v^tq} qv^tY

        Therefore, we must solve for :math:`q` and :math:`Y` in :math:`Tq = u` and :math:`TY = D`.
        As :math:`T` is now tridiagonal, we shall use Thomas' algorithm.

        Define:

        *   :math:`a = [a_0, \ a_1, \ ..., \ a_{N-2}]` as :math:`T`'s lower diagonal of :math:`N-1` elements,
            such that :math:`a_0 = a_1 = ... = a_{N-2} = 1`, so this diagonal is filled with ones;
        *   :math:`b = [b_0, \ b_1, \ ..., \ b_{N-2}, \ b_{N-1}]` as :math:`T`'s main diagonal of :math:`N` elements,
            such that :math:`b_0 = b_{N-1} = 3`, and :math:`b_1 = b_2 = ... = b_{N-2} = 4`;
        *   :math:`c = [c_0, \ c_1, \ ..., \ c_{N-2}]` as :math:`T`'s upper diagonal of :math:`N-1` elements,
            such that :math:`c_0 = c_1 = ... = c_{N-2} = 1`: this diagonal is also filled with ones.

        If, according to Thomas' algorithm, we define:

        .. math::
            c'_0 &= \frac{c_0}{b_0} & \\
            c'_i &= \frac{c_i}{b_i - a_{i-1} c'_{i-1}}, & \quad \forall i \in \{1, ..., N-2\} \\
            & & \\
            u'_0 &= \frac{u_0}{b_0} & \\
            u'_i &= \frac{u_i - a_{i-1} u'_{i-1}}{b_i - a_{i-1} c'_{i-1}}, & \quad \forall i \in \{1, ..., N-1\} \\
            & & \\
            D'_0 &= \frac{1}{b_0} D_0 & \\
            D'_i &= \frac{1}{b_i - a_{i-1} c'_{i-1}} (D_i - a_{i-1} D'_{i-1}), & \quad \forall i \in \{1, ..., N-1\}

        Then:

        .. math::
            c'_0     &= \frac{1}{3} & \\
            c'_i     &= \frac{1}{4 - c'_{i-1}}, & \quad \forall i \in \{1, ..., N-2\} \\
            & & \\
            u'_0     &= \frac{1}{3} & \\
            u'_i     &= \frac{-u'_{i-1}}{4 - c'_{i-1}} = -c'_i u'_{i-1}, & \quad \forall i \in \{1, ..., N-2\} \\
            u'_{N-1} &= \frac{1 - u'_{N-2}}{3 - c'_{N-2}} & \\
            & & \\
            D'_0     &= \frac{1}{3} (4A_0 + 2A_1) & \\
            D'_i     &= \frac{1}{4 - c'_{i-1}} (4A_i + 2A_{i+1} - D'_{i-1}) & \\
            &= c_i (4A_i + 2A_{i+1} - D'_{i-1}), & \quad \forall i \in \{1, ..., N-2\} \\
            D'_{N-1} &= \frac{1}{3 - c'_{N-2}} (4A_{N-1} + 2A_N - D'_{N-2}) &

        Finally, we can do Backward Substitution to find :math:`q` and :math:`Y`:

        .. math::
            q_{N-1} &= u'_{N-1} & \\
            q_i     &= u'_{i} - c'_i q_{i+1}, & \quad \forall i \in \{0, ..., N-2\} \\
            & & \\
            Y_{N-1} &= D'_{N-1} & \\
            Y_i     &= D'_i - c'_i Y_{i+1},   & \quad \forall i \in \{0, ..., N-2\}

        With those values, we can finally calculate :math:`H_1 = Y - \frac{1}{1 + v^tq} qv^tY`.
        Given that :math:`v_0 = v_{N-1} = 1`, and :math:`v_1 = v_2 = ... = v_{N-2} = 0`, its dot products
        with :math:`q` and :math:`Y` are respectively :math:`v^tq = q_0 + q_{N-1}` and
        :math:`v^tY = Y_0 + Y_{N-1}`. Thus:

        .. math::
            H_1 = Y - \frac{1}{1 + q_0 + q_{N-1}} q(Y_0 + Y_{N-1})

        Once we have :math:`H_1`, we can get :math:`H_2` (the array of second handles) as follows:

        .. math::
            H_{2, i}   &= 2A_{i+1} - H_{1, i+1}, & \quad \forall i \in \{0, ..., N-2\} \\
            H_{2, N-1} &= 2A_0 - H_{1, 0} &

        Because the matrix :math:`R` always follows the same pattern (and thus :math:`T, u, v` as well),
        we can define a memo list for :math:`c'` and :math:`u'` to avoid recalculation. We cannot
        memoize :math:`D` and :math:`Y`, however, because they are always different matrices. We
        cannot make a memo for :math:`q` either, but we can calculate it faster because :math:`u'`
        can be memoized.

    Parameters
    ----------
    anchors
        Anchors of a closed cubic spline.

    Returns
    -------
    :class:`tuple` [:class:`~.Point3D_Array`, :class:`~.Point3D_Array`]
        A tuple of two arrays: one containing the 1st handle for every curve in
        the closed cubic spline, and the other containing the 2nd handles.
    r   r3   Nr|   rE   r?   rK   )r8   r]   rT   CP_CLOSED_MEMOsizerS   UP_CLOSED_MEMOrV   )r   Arr   rN   len_memocpuprY   cp_last_divisionup_lastqDpAUXYH1H2s                   r,   r   r     s?   F 	
7A	
QA
'!*C "H!a%Xa!e__Xa!e__&9H9&9H9 xQ'' 	' 	'ARAY'BqEUFRAY&BqEEGa!eG$Ga!eG$ A1q5	M*!bQi-0G 	!SAAa!eH1q5"b!! ( (!ur!uqQx''! 
1c(		B
ae)a!ABB%i
CFQJBqE1a!e__ - -1Q"QU)+,1 CAJAE$:;Bq1uI
 	A1q5"b!! ( (!ur!uqQx''! 
Q!ad(Qq1uX%&*adQq1uXo>	>B 
1c(		B!A#JAaC(Bq1q5yMAaD2a5 Bq1uIr6Mr-         ?c                   t          j        |           }|j        d         dz
  }|j        d         }t          j        }||dz
  k     rPt          j        |dz
            }t          |d|<   t          ||dz
            D ]}dd||dz
           z
  z  ||<   |ant          d|dz
           }t          j        ||f          }d|d         z  |d         z   |d<   d|d|dz
           z  d|d|         z  z   }t          d|dz
            D ]%}||         ||dz
           ||dz
           z
  z  ||<   &ddd||dz
           z  z
  z  d||dz
           z  ||         z   d||dz
           z  z
  z  ||dz
  <   |}	t          |dz
  d	d	          D ]"}||         ||         |	|dz            z  z
  |	|<   #t          j        ||f          }
d|d|         z  |	d|         z
  |
d|dz
  <   d||         |	|dz
           z   z  |
|dz
  <   |	|
fS )
uT  Special case of :func:`get_smooth_cubic_bezier_handle_points`,
    when the ``anchors`` do not form a closed loop.

    .. note::
        A system of equations must be solved to get the first handles of
        every Bèzier curve (referred to as :math:`H_1`).
        Then :math:`H_2` (the second handles) can be obtained separately.

        .. seealso::
            The equations were obtained from:

            * `Smooth Bézier Spline Through Prescribed Points. (2012). Particle in Cell Consulting LLC. <https://www.particleincell.com/2012/bezier-splines/>`_
            * `Conditions on control points for continuous curvature. (2016). Jaco Stuifbergen. <http://www.jacos.nl/jacos_html/spline/theory/theory_2.html>`_

        .. warning::
            The equations in the first webpage have some typos which were corrected in the comments.

        In general, if there are :math:`N+1` anchors, there will be :math:`N` Bézier curves
        and thus :math:`N` pairs of handles to find. We must solve the following
        system of equations for the 1st handles (example for :math:`N = 5`):

        .. math::
            \begin{pmatrix}
                2 & 1 & 0 & 0 & 0 \\
                1 & 4 & 1 & 0 & 0 \\
                0 & 1 & 4 & 1 & 0 \\
                0 & 0 & 1 & 4 & 1 \\
                0 & 0 & 0 & 2 & 7
            \end{pmatrix}
            \begin{pmatrix}
                H_{1,0} \\
                H_{1,1} \\
                H_{1,2} \\
                H_{1,3} \\
                H_{1,4}
            \end{pmatrix}
            =
            \begin{pmatrix}
                A_0 + 2A_1 \\
                4A_1 + 2A_2 \\
                4A_2 + 2A_3 \\
                4A_3 + 2A_4 \\
                8A_4 + A_5
            \end{pmatrix}

        which will be expressed as :math:`TH_1 = D`.
        :math:`T` is a tridiagonal matrix, so the system can be solved in :math:`O(N)`
        operations. Here we shall use Thomas' algorithm or the tridiagonal matrix
        algorithm.

        .. seealso::
            `Tridiagonal matrix algorithm. Wikipedia. <https://en.wikipedia.org/wiki/Tridiagonal_matrix_algorithm>`_

        Define:

        *   :math:`a = [a_0, \ a_1, \ ..., \ a_{N-2}]` as :math:`T`'s lower diagonal of :math:`N-1` elements,
            such that :math:`a_0 = a_1 = ... = a_{N-3} = 1`, and :math:`a_{N-2} = 2`;
        *   :math:`b = [b_0, \ b_1, \ ..., \ b_{N-2}, \ b_{N-1}]` as :math:`T`'s main diagonal of :math:`N` elements,
            such that :math:`b_0 = 2`, :math:`b_1 = b_2 = ... = b_{N-2} = 4`, and :math:`b_{N-1} = 7`;
        *   :math:`c = [c_0, \ c_1, \ ..., \ c_{N-2}]` as :math:`T`'s upper diagonal of :math:`{N-1}` elements,
            such that :math:`c_0 = c_1 = ... = c_{N-2} = 1`: this diagonal is filled with ones.

        If, according to Thomas' algorithm, we define:

        .. math::
            c'_0 &= \frac{c_0}{b_0} & \\
            c'_i &= \frac{c_i}{b_i - a_{i-1} c'_{i-1}}, & \quad \forall i \in \{1, ..., N-2\} \\
            & & \\
            D'_0 &= \frac{1}{b_0} D_0 & \\
            D'_i &= \frac{1}{b_i - a_{i-1} c'{i-1}} (D_i - a_{i-1} D'_{i-1}), & \quad \forall i \in \{1, ..., N-1\}

        Then:

        .. math::
            c'_0     &= 0.5 & \\
            c'_i     &= \frac{1}{4 - c'_{i-1}}, & \quad \forall i \in \{1, ..., N-2\} \\
            & & \\
            D'_0     &= 0.5A_0 + A_1 & \\
            D'_i     &= \frac{1}{4 - c'_{i-1}} (4A_i + 2A_{i+1} - D'_{i-1}) & \\
            &= c_i (4A_i + 2A_{i+1} - D'_{i-1}), & \quad \forall i \in \{1, ..., N-2\} \\
            D'_{N-1} &= \frac{1}{7 - 2c'_{N-2}} (8A_{N-1} + A_N - 2D'_{N-2}) &

        Finally, we can do Backward Substitution to find :math:`H_1`:

        .. math::
            H_{1, N-1} &= D'_{N-1} & \\
            H_{1, i}   &= D'_i - c'_i H_{1, i+1}, & \quad \forall i \in \{0, ..., N-2\}

        Once we have :math:`H_1`, we can get :math:`H_2` (the array of second handles) as follows:

        .. math::
            H_{2, i}   &= 2A_{i+1} - H_{1, i+1}, & \quad \forall i \in \{0, ..., N-2\} \\
            H_{2, N-1} &= 0.5A_N   + 0.5H_{1, N-1} &

        As the matrix :math:`T` always follows the same pattern, we can define a memo list
        for :math:`c'` to avoid recalculation. We cannot do the same for :math:`D`, however,
        because it is always a different matrix.

    Parameters
    ----------
    anchors
        Anchors of an open cubic spline.

    Returns
    -------
    :class:`tuple` [:class:`~.Point3D_Array`, :class:`~.Point3D_Array`]
        A tuple of two arrays: one containing the 1st handle for every curve in
        the open cubic spline, and the other containing the 2nd handles.
    r   r3   Nr|   r   r?         rK   )r8   r]   rT   CP_OPEN_MEMOr   rS   rV   )r   r   rr   rN   r   r   rY   r   r   r   r   s              r,   r   r   7  sU   d 	
7A	
QA
'!*C  H!a%Xa!e__$9H9xQ'' 	( 	(ARAY'BqEE'AE'" 
1c(		B!A$J1BqE
aAE	l
Q1Q3Z
'C1a!e__ 1 11QUbQi/01a!bQi-'(Q1q5\AaD-@1r!a%y=-PQBq1uI
 
B1q5"b!! * *111q5	))1 
1c(		B!A#JAaC(Bq1q5yMqtbQi'(Bq1uIr6Mr-   a0r    h0h1a1r#   c                    d S r)   r*   r   r   r   r   s       r,   $get_quadratic_approximation_of_cubicr     s	     cr-   r"   c                    d S r)   r*   r   s       r,   r   r     s	     #r-   r6   %QuadraticSpline | QuadraticBezierPathc                <   t          j        |           }t          j        |          }t          j        |          }t          j        |          }t          d ||||fD                       rd|j        d         }	}n7t          d ||||fD                       r|j        \  }}	nt	          d          dd|z  |z   z  }
dd|z  |z   z  }d|
|z   z  }t          j        d	|z  |	f          }||dd
d	<   |
|dd
d	<   ||dd
d	<   ||dd
d	<   ||dd
d	<   ||dd
d	<   |S )u  If ``a0``, ``h0``, ``h1`` and ``a1`` are the control points of a cubic
    Bézier curve, approximate the curve with two quadratic Bézier curves and
    return an array of 6 points, where the first 3 points represent the first
    quadratic curve and the last 3 represent the second one.

    Otherwise, if ``a0``, ``h0``, ``h1`` and ``a1`` are _arrays_ of :math:`N`
    points representing :math:`N` cubic Bézier curves, return an array of
    :math:`6N` points where each group of :math:`6` consecutive points
    approximates each of the :math:`N` curves in a similar way as above.

    .. note::
        If the cubic spline given by the original cubic Bézier curves is
        smooth, this algorithm will generate a quadratic spline which is also
        smooth.

        If a cubic Bézier is given by

        .. math::
            C(t) = (1-t)^3 A_0 + 3(1-t)^2 t H_0 + 3(1-t)t^2 H_1 + t^3 A_1

        where :math:`A_0`, :math:`H_0`, :math:`H_1` and :math:`A_1` are its
        control points, then this algorithm should generate two quadratic
        Béziers given by

        .. math::
            Q_0(t) &= (1-t)^2 A_0 + 2(1-t)t M_0 + t^2 K \\
            Q_1(t) &= (1-t)^2 K + 2(1-t)t M_1 + t^2 A_1

        where :math:`M_0` and :math:`M_1` are the respective handles to be
        found for both curves, and :math:`K` is the end anchor of the 1st curve
        and the start anchor of the 2nd, which must also be found.

        To solve for :math:`M_0`, :math:`M_1` and :math:`K`, three conditions
        can be imposed:

        1.  :math:`Q_0'(0) = \frac{1}{2}C'(0)`. The derivative of the first
            quadratic curve at :math:`t = 0` should be proportional to that of
            the original cubic curve, also at :math:`t = 0`. Because the cubic
            curve is split into two parts, it is necessary to divide this by
            two: the speed of a point travelling through the curve should be
            half of the original. This gives:

            .. math::
                Q_0'(0) &= \frac{1}{2}C'(0) \\
                2(M_0 - A_0) &= \frac{3}{2}(H_0 - A_0) \\
                2M_0 - 2A_0 &= \frac{3}{2}H_0 - \frac{3}{2}A_0 \\
                2M_0 &= \frac{3}{2}H_0 + \frac{1}{2}A_0 \\
                M_0 &= \frac{1}{4}(3H_0 + A_0)

        2.  :math:`Q_1'(1) = \frac{1}{2}C'(1)`. The derivative of the second
            quadratic curve at :math:`t = 1` should be half of that of the
            original cubic curve for the same reasons as above, also at
            :math:`t = 1`. This gives:

            .. math::
                Q_1'(1) &= \frac{1}{2}C'(1) \\
                2(A_1 - M_1) &= \frac{3}{2}(A_1 - H_1) \\
                2A_1 - 2M_1 &= \frac{3}{2}A_1 - \frac{3}{2}H_1 \\
                -2M_1 &= -\frac{1}{2}A_1 - \frac{3}{2}H_1 \\
                M_1 &= \frac{1}{4}(3H_1 + A_1)

        3.  :math:`Q_0'(1) = Q_1'(0)`. The derivatives of both quadratic curves
            should match at the point :math:`K`, in order for the final spline
            to be smooth. This gives:

            .. math::
                Q_0'(1) &= Q_1'(0) \\
                2(K - M_0) &= 2(M_1 - K) \\
                2K - 2M_0 &= 2M_1 - 2K \\
                4K &= 2M_0 + 2M_1 \\
                K &= \frac{1}{2}(M_0 + M_1)

        This is sufficient to find proper control points for the quadratic
        Bézier curves.

    Parameters
    ----------
    a0
        The start anchor of a single cubic Bézier curve, or an array of
        :math:`N` start anchors for :math:`N` curves.
    h0
        The first handle of a single cubic Bézier curve, or an array of
        :math:`N` first handles for :math:`N` curves.
    h1
        The second handle of a single cubic Bézier curve, or an array of
        :math:`N` second handles for :math:`N` curves.
    a1
        The end anchor of a single cubic Bézier curve, or an array of
        :math:`N` end anchors for :math:`N` curves.

    Returns
    -------
    result
        An array containing either 6 points for 2 quadratic Bézier curves
        approximating the original cubic curve, or :math:`6N` points for
        :math:`2N` quadratic curves approximating :math:`N` cubic curves.

    Raises
    ------
    ValueError
        If ``a0``, ``h0``, ``h1`` and ``a1`` have different dimensions, or
        if their number of dimensions is not 1 or 2.
    c              3  ,   K   | ]}|j         d k    V  dS )r3   NndimrM   re   s     r,   	<genexpr>z7get_quadratic_approximation_of_cubic.<locals>.<genexpr>Q  s(      
9
9S38q=
9
9
9
9
9
9r-   r3   r   c              3  ,   K   | ]}|j         d k    V  dS )r?   Nr   r   s     r,   r   z7get_quadratic_approximation_of_cubic.<locals>.<genexpr>S  s(      ;;sSX];;;;;;r-   z/All arguments must be Point3D or Point3D_Array.g      ?rE   r      Nr?   r|      )r8   r]   allrT   
ValueErrorrS   )r   r   r   r   a0ch0ch1ca1c
num_curvesrN   m0m1kresults                 r,   r   r     s`   Z *R..C
*R..C
*R..C
*R..C

9
9S#sC$8
9
9
999 LSYq\C

	;;sCc&:;;;	;	; L)
CCJKKK	S3	B	S3	BrBwAXq:~s+,,FF14a4LF14a4LF14a4LF14a4LF14a4LF14a4LMr-   boolc                L   | d         | d         }}d}d}|||z  z   }t          |d         |d         z
            |d         k    rdS t          |d         |d         z
            |d         k    rdS t          t          |d         |d         z
            |d         k              S )aF  Returns ``True`` if the spline given by ``points`` is closed, by
    checking if its first and last points are close to each other, or``False``
    otherwise.

    .. note::

        This function reimplements :meth:`np.allclose`, because repeated
        calling of :meth:`np.allclose` for only 2 points is inefficient.

    Parameters
    ----------
    points
        An array of points defining a spline.

    Returns
    -------
    :class:`bool`
        Whether the first and last points of the array are close enough or not
        to be considered the same, thus considering the defined spline as
        closed.

    Examples
    --------
    .. code-block:: pycon

        >>> import numpy as np
        >>> from manim import is_closed
        >>> is_closed(
        ...     np.array(
        ...         [
        ...             [0, 0, 0],
        ...             [1, 2, 3],
        ...             [3, 2, 1],
        ...             [0, 0, 0],
        ...         ]
        ...     )
        ... )
        True
        >>> is_closed(
        ...     np.array(
        ...         [
        ...             [0, 0, 0],
        ...             [1, 2, 3],
        ...             [3, 2, 1],
        ...             [1e-10, 1e-10, 1e-10],
        ...         ]
        ...     )
        ... )
        True
        >>> is_closed(
        ...     np.array(
        ...         [
        ...             [0, 0, 0],
        ...             [1, 2, 3],
        ...             [3, 2, 1],
        ...             [1e-2, 1e-2, 1e-2],
        ...         ]
        ...     )
        ... )
        False
    r   rK   gh㈵>g:0yE>Fr3   r?   )absr  )r%   r   r   rtolatol	tolerances         r,   r   r   f  s    | F2J3EDDte|#I
3q6E!H	!,,u
3q6E!H	!,,uCFU1X%&&)A,6777r-   ư>pointcontrol_pointsround_toc           
     b    t           fd|D                       st          d  d| d          t          j        |          }t	          |          dz
  }g }t                     D ]\  }}|dd|f         }g }t          |dd          D ]}	t          ||	          }
g }d}t          |	dd          D ]E}t          |	|          |z  }|||         z  }|	dk    r||z  }|                    |           |dz  }F|                    |
t          t          j        |                    z             t          d	 |D                       rt          j
                            |ddd                   }|                                }t	          |          dk    r7t          j        |t          t          j        d|z                                }|                    |           d
 |D             }t!          t          j        |          }t          j        d |D                       }|S )a  Obtains the proportion along the bezier curve corresponding to a given point
    given the bezier curve's control points.

    The bezier polynomial is constructed using the coordinates of the given point
    as well as the bezier curve's control points. On solving the polynomial for each dimension,
    if there are roots common to every dimension, those roots give the proportion along the
    curve the point is at. If there are no real roots, the point does not lie on the curve.

    Parameters
    ----------
    point
        The Cartesian Coordinates of the point whose parameter
        should be obtained.
    control_points
        The Cartesian Coordinates of the ordered control
        points of the bezier curve on which the point may
        or may not lie.
    round_to
        A float whose number of decimal places all values
        such as coordinates of points will be rounded.

    Returns
    -------
        np.ndarray[float]
            List containing possible parameters (the proportions along the bezier curve)
            for the given point on the given bezier curve.
            This usually only contains one or zero elements, but if the
            point is, say, at the beginning/end of a closed loop, may return
            a list with more than 1 value, corresponding to the beginning and
            end etc. of the loop.

    Raises
    ------
    :class:`ValueError`
        When ``point`` and the control points have different shapes.
    c              3  l   K   | ].}t          j                  t          j        |          k    V  /d S r)   )r8   rT   )rM   c_pr  s     r,   r   z;proportions_along_bezier_curve_for_point.<locals>.<genexpr>  s8      JJCrx"(3--/JJJJJJr-   zPoint z and Control Points z have different shapes.r3   NrK   r   c              3  "   K   | ]
}|d k    V  dS )r   Nr*   )rM   terms     r,   r   z;proportions_along_bezier_curve_for_point.<locals>.<genexpr>  s&      ++Ttqy++++++r-   c                &    g | ]}d  |D             S )c                (    g | ]}|j         d k    |S )r   )imag)rM   roots     r,   rO   zGproportions_along_bezier_curve_for_point.<locals>.<listcomp>.<listcomp>  s    :::t49>>d>>>r-   r*   )rM   rootlists     r,   rO   z<proportions_along_bezier_curve_for_point.<locals>.<listcomp>  s'    QQQx::x:::QQQr-   c                F    g | ]}d |j         cxk    rdk    n n|j         S )r   r3   )real)rM   rs     r,   rO   z<proportions_along_bezier_curve_for_point.<locals>.<listcomp>  s=    CCCA!qv2B2B2B2B2B2B2B2B2B2B2B2Br-   )r   r   r8   rd   len	enumeraterV   r   appendsum
polynomial
Polynomialrootsaroundr   log10r   intersect1dr]   )r  r  r  nr$  rN   coordcontrol_coordsterms
term_power
outercoeffr  signsubterm_num
innercoeffsubtermbezier_polynompolynom_rootsr  s   `                  r,   r   r     se   X JJJJ>JJJJJ 
WUWWWWW
 
 	
 Xn--NNaAE&& $ $
U'3/2r** 	; 	;J:..JDD$ZR88  #J<<tC
$~k'BB??u$GG$$$
LLc"(4..&9&99::::++U+++++ 	 11%"+>>&,,..}!!ImS!h,9O9O5P5PQQM]####QQ5QQQE 2>5))EZCCCCCDDFMr-   c                J    t          | ||          }t          |          dk    S )a  Checks if a given point lies on the bezier curves with the given control points.

    This is done by solving the bezier polynomial with the point as the constant term; if
    any real roots exist, the point lies on the bezier curve.

    Parameters
    ----------
    point
        The Cartesian Coordinates of the point to check.
    control_points
        The Cartesian Coordinates of the ordered control
        points of the bezier curve on which the point may
        or may not lie.
    round_to
        A float whose number of decimal places all values
        such as coordinates of points will be rounded.

    Returns
    -------
    bool
        Whether the point lies on the curve.
    r   )r   r  )r  r  r  r$  s       r,   r   r     s%    6 5UNHUUEu::>r-   )r%   r   r&   r'   )r%   r.   r&   r/   )r%   r1   r&   r/   )r%   r   r^   r_   r`   r_   r&   r   )r%   r   r4   r_   r&   r$   )r~   r   r   r   r&   r   )r%   r   r   r   r&   r$   )r   r   r   r   r&   r   )r   r_   r   r_   r   r_   r&   r_   )r   r_   r   r_   r   r   r&   r   )r   r   r   r   r   r_   r&   r   )r   r   r   r   r   r   r&   r   )r   r   r   r   r   r5   r&   r   )r   r_   r   r_   r   r_   r&   r   )r   r_   r   r_   r&   r_   )r   r   r   r   r&   r   )r   r   r   r   r&   r   )r   r_   r   r_   r   r_   r&   r_   )r   r_   r   r_   r   r   r&   r   )r   r   r   r   r   r   r&   r   )r   r   r   r   r   r   r&   r   )r   r_   r   r_   r   r_   r   r_   r   r_   r&   r_   )r   r_   r   r_   r   r_   r   r_   r   r   r&   r   )r   r_   r   r_   r   r_   r   r_   r   r   r&   r   )r   r!   r&   r   )
r   r    r   r    r   r    r   r    r&   r#   )
r   r!   r   r!   r   r!   r   r!   r&   r"   )
r   r6   r   r6   r   r6   r   r6   r&   r   )r%   r   r&   r  )r  )r  r    r  r   r  r_   r&   r   )r  r    r  r   r  r_   r&   r  )7__doc__
__future__r   __all__collections.abcr   r   	functoolsr   typingr   r   numpyr8   manim.utils.simple_functionsr   manim.typingr   r   r   r   r   r   r   r   r    r!   r"   r#   r$   r   r   r   rV   r}   __annotations__r   r   r   r	   r
   r   r   r   r   rd   r   r   r   r   r   r   r   r   r   r*   r-   r,   <module>r?     s   2 2 2 " " " " " "  $ / . . . . . . .       * * * * * * * *     / / / / / /                              ( 
A A A 
A
 
7 7 7 
7
r r r rjV V V Vrw# w# w# w#v	 3I2HuuQxx2H2H2H  H H H Hj j j jZ~1 ~1 ~1 ~1B8 8 8 8| 
 E E E 
 E 
 M M M 
 M 
 K K K 
 K 
 U U U 
 U -  -  -  -F) ) ) )X 
 / / / 
 / 
 5 5 5 
 5   " 
 M M M 
 M 
 Q Q Q 
 Q 
 U U U 
 U&6 &6 &6 &6R 
   
 
   
' ' ' 'V(C (C (C (CV 5'""5'""^ ^ ^ ^B	 rxV V V Vr 
   

 
   
D D D DNF8 F8 F8 F8X S S S S Sr       r-   