
    ljB                       U d Z ddlmZ g dZddlZddlZddlmZm	Z	m
Z
 ddlmZmZ ddlmZ ddlZddlmZ dd	lmZ dd
lmZ ddlmZ ddlmZ ddlmZmZ ddlm Z  ddl!m"Z" ddl#m$Z$m%Z%m&Z&m'Z' ddl(m)Z) ddl*m+Z+ ddl,m-Z- ddl.m/Z/m0Z0 ddl1m2Z2m3Z3m4Z4m5Z5m6Z6m7Z7m8Z8m9Z9 ddl:m;Z;m<Z< ddl=m>Z> erddl?m@Z@mAZAmBZBmCZCmDZD e2e3e5e4gZEdeFd<    G d de+          ZG G d deG          ZH G d  d!eG          ZIdS )"z$Mobjects representing vector fields.    )annotations)VectorFieldArrowVectorFieldStreamLinesN)CallableIterableSequence)ceilfloor)TYPE_CHECKING)Image)UpdateFromAlphaFunc)Vector)CoordinateSystem   )config)AnimationGroup
SuccessionCreate)ShowPassingFlash)OUTRIGHTUPRendererType)Mobject)VGroup)get_vectorized_mobject_class)interpolateinverse_interpolate)BLUE_EGREENREDYELLOW
ManimColorParsableManimColorcolor_to_rgbrgb_to_color)ease_out_sinelinearsigmoid)FloatRGBFloatRGB_ArrayFloatRGBA_ArrayPoint3DVector3DlistDEFAULT_SCALAR_FIELD_COLORSc                       e Zd ZdZddddefd4 fdZed5d            Zed6d            Zd7dZ		 	 	 d8d9d$Z
	 	 	 d8d:d%Z	 	 d;d<d(Z	 	 d;d=d)Zd>d*Zd?d@d.ZdAd3Z xZS )Br   a  A vector field.

    Vector fields are based on a function defining a vector at every position.
    This class does by default not include any visible elements but provides
    methods to move other :class:`~.Mobject` s along the vector field.

    Parameters
    ----------
    func
        The function defining the rate of change at every position of the `VectorField`.
    color
        The color of the vector field. If set, position-specific coloring is disabled.
    color_scheme
        A function mapping a vector to a single value. This value gives the position in the color gradient defined using `min_color_scheme_value`, `max_color_scheme_value` and `colors`.
    min_color_scheme_value
        The value of the color_scheme function to be mapped to the first color in `colors`. Lower values also result in the first color of the gradient.
    max_color_scheme_value
        The value of the color_scheme function to be mapped to the last color in `colors`. Higher values also result in the last color of the gradient.
    colors
        The colors defining the color gradient of the vector field.
    kwargs
        Additional arguments to be passed to the :class:`~.VGroup` constructor

    Nr   r   funcCallable[[Point3D], Vector3D]colorParsableManimColor | Nonecolor_scheme"Callable[[Vector3D], float] | Nonemin_color_scheme_valuefloatmax_color_scheme_valuecolorsSequence[ParsableManimColor]c                n     t                      j        di | | _        |gd _        |dd}| _        t          j        t          t          t          |                               _
        d fd
}| _         fd _        n d _        t          j        |           _        d  _        d S )NFvecr1   returnr<   c                @    t           j                            |           S N)nplinalgnorm)rA   s    U/home/agentuser/manim-venv/lib/python3.11/site-packages/manim/mobject/vector_field.pyr9   z*VectorField.__init__.<locals>.color_schemed   s    9>>#...    posr0   r-   c                                        |           }t          j                            |                    }t	          |          }|t          j                  dz
  z  }j        t          |                   }j        t          t          |dz             t          j                  dz
                     }|dz  }t          |||          S N   )
r5   rE   clipr9   r    lenrgbsintminr   )	rJ   rA   color_valuealphac1c2r=   r;   selfs	         rH   
pos_to_rgbz(VectorField.__init__.<locals>.pos_to_rgbj   s    iinn g%%c**** 
 ,** 
 TY!++#yU4#yS^^S^^a=O)P)PQ
"2r5111rI   c                H    t                              |                     S rD   )r(   rX   )rJ   rW   s    rH   <lambda>z&VectorField.__init__.<locals>.<lambda>}   s    L9M9M,N,N rI   T )rA   r1   rB   r<   )rJ   r0   rB   r-   )super__init__r5   single_colorr9   rE   arrayr2   mapr'   rP   rX   pos_to_colorr%   parser7   submob_movement_updater)
rW   r5   r7   r9   r;   r=   r>   kwargsrX   	__class__s
   `   ``   rH   r]   zVectorField.__init__T   s     	""6"""	= %D#/ / / / !-D(*c,6O6O1P1P(Q(QDI2 2 2 2 2 2 2 2$ )DO N N N ND $D#)%00DJ'+$$$rI   "Callable[[np.ndarray], np.ndarray]shift_vector
np.ndarrayrB   c                      fdS )aY  Shift a vector field function.

        Parameters
        ----------
        func
            The function defining a vector field.
        shift_vector
            The shift to be applied to the vector field.

        Returns
        -------
        `Callable[[np.ndarray], np.ndarray]`
            The shifted vector field function.

        c                      | z
            S rD   r[   )pr5   rg   s    rH   rZ   z(VectorField.shift_func.<locals>.<lambda>   s    a,.// rI   r[   )r5   rg   s   ``rH   
shift_funczVectorField.shift_func   s    ( 0/////rI   scalarc                      fdS )a  Scale a vector field function.

        Parameters
        ----------
        func
            The function defining a vector field.
        scalar
            The scalar to be applied to the vector field.

        Examples
        --------
        .. manim:: ScaleVectorFieldFunction

            class ScaleVectorFieldFunction(Scene):
                def construct(self):
                    func = lambda pos: np.sin(pos[1]) * RIGHT + np.cos(pos[0]) * UP
                    vector_field = ArrowVectorField(func)
                    self.add(vector_field)
                    self.wait()

                    func = VectorField.scale_func(func, 0.5)
                    self.play(vector_field.animate.become(ArrowVectorField(func)))
                    self.wait()

        Returns
        -------
        `Callable[[np.ndarray], np.ndarray]`
            The scaled vector field function.

        c                      | z            S rD   r[   )rk   r5   rm   s    rH   rZ   z(VectorField.scale_func.<locals>.<lambda>   s    a&j)) rI   r[   )r5   rm   s   ``rH   
scale_funczVectorField.scale_func   s    F *)))))rI   coordinate_systemr   c                8    |                      fd           dS )a  Scale the vector field to fit a coordinate system.

        This method is useful when the vector field is defined in a coordinate system
        different from the one used to display the vector field.

        This method can only be used once because it transforms the origin of each vector.

        Parameters
        ----------
        coordinate_system
            The coordinate system to fit the vector field to.

        c                     j         |  S rD   )coords_to_point)rJ   rq   s    rH   rZ   z6VectorField.fit_to_coordinate_system.<locals>.<lambda>   s    (I(9(I3(O rI   N)apply_function)rW   rq   s    `rH   fit_to_coordinate_systemz$VectorField.fit_to_coordinate_system   s)     	OOOOPPPPPrI   rM   Fmobr   dtsubstepsrQ   	pointwiseboolc                     dd||z  t          |          D ]Q}|r|                     fd           |                      |                                                     R S )	aN  Nudge a :class:`~.Mobject` along the vector field.

        Parameters
        ----------
        mob
            The mobject to move along the vector field
        dt
            A scalar to the amount the mobject is moved along the vector field.
            The actual distance is based on the magnitude of the vector field.
        substeps
            The amount of steps the whole nudge is divided into. Higher values
            give more accurate approximations.
        pointwise
            Whether to move the mobject along the vector field. If `False` the
            vector field takes effect on the center of the given
            :class:`~.Mobject`. If `True` the vector field takes effect on the
            points of the individual points of the :class:`~.Mobject`,
            potentially distorting it.

        Returns
        -------
        VectorField
            This vector field.

        Examples
        --------

        .. manim:: Nudging

            class Nudging(Scene):
                def construct(self):
                    func = lambda pos: np.sin(pos[1] / 2) * RIGHT + np.cos(pos[0] / 2) * UP
                    vector_field = ArrowVectorField(
                        func, x_range=[-7, 7, 1], y_range=[-4, 4, 1], length_func=lambda x: x / 2
                    )
                    self.add(vector_field)
                    circle = Circle(radius=2).shift(LEFT)
                    self.add(circle.copy().set_color(GRAY))
                    dot = Dot().move_to(circle)

                    vector_field.nudge(circle, -2, 60, True)
                    vector_field.nudge(dot, -2, 60)

                    circle.add_updater(vector_field.get_nudge_updater(pointwise=True))
                    dot.add_updater(vector_field.get_nudge_updater())
                    self.add(circle, dot)
                    self.wait(6)

        rk   Sequence[float]	step_sizer<   rB   c                   |                      |          }|                      |||dz  z  z             }|                      |||dz  z  z             }|                      |||z  z             }|dz  |d|z  z   d|z  z   |z   z  S )a  Returns the change in position of a point along a vector field.
            Parameters
            ----------
            p
               The position of each point being moved along the vector field.
            step_size
               A scalar that is used to determine how much a point is shifted in a single step.

            Returns
            -------
            float
               How much the point is shifted.
                  ?g      @g       @)r5   )rW   rk   r~   k_1k_2k_3k_4s          rH   runge_kuttaz&VectorField.nudge.<locals>.runge_kutta  s     ))A,,C))A	S3Y 7788C))A	S3Y 7788C))A	C/00Cs?cC#Ioc	&AC&GHHrI   c                $    |  |           z   S rD   r[   )rk   r   rW   r~   s    rH   rZ   z#VectorField.nudge.<locals>.<lambda>  s    QT1i1P1P-P rI   )rk   r}   r~   r<   rB   r<   )rangeru   shift
get_center)rW   rw   rx   ry   rz   _r   r~   s   `     @@rH   nudgezVectorField.nudge   s    r	I 	I 	I 	I( M	x 	J 	JA J""#P#P#P#P#P#PQQQQ		++dCNN,<,<iHHIIIIrI   c                J    | j         D ]}|                     ||||           | S )ag  Apply a nudge along the vector field to all submobjects.

        Parameters
        ----------
        dt
            A scalar to the amount the mobject is moved along the vector field.
            The actual distance is based on the magnitude of the vector field.
        substeps
            The amount of steps the whole nudge is divided into. Higher values
            give more accurate approximations.
        pointwise
            Whether to move the mobject along the vector field. See :meth:`nudge` for details.

        Returns
        -------
        VectorField
            This vector field.

        )submobjectsr   )rW   rx   ry   rz   rw   s        rH   nudge_submobjectszVectorField.nudge_submobjects#  s6    2 # 	5 	5CJJsB)4444rI   speed#Callable[[Mobject, float], Mobject]c                      fdS )a  Get an update function to move a :class:`~.Mobject` along the vector field.

        When used with :meth:`~.Mobject.add_updater`, the mobject will move along the vector field, where its speed is determined by the magnitude of the vector field.

        Parameters
        ----------
        speed
            At `speed=1` the distance a mobject moves per second is equal to the magnitude of the vector field along its path. The speed value scales the speed of such a mobject.
        pointwise
            Whether to move the mobject along the vector field. See :meth:`nudge` for details.

        Returns
        -------
        Callable[[Mobject, float], Mobject]
            The update function.
        c                :                         | |z            S N)rz   )r   )rw   rx   rz   rW   r   s     rH   rZ   z/VectorField.get_nudge_updater.<locals>.<lambda>U  s    tzz#rEzYzOO rI   r[   rW   r   rz   s   ```rH   get_nudge_updaterzVectorField.get_nudge_updater@  s    * POOOOOOrI   c                |    |                                   fd| _        |                     | j                   | S )a  Start continuously moving all submobjects along the vector field.

        Calling this method multiple times will result in removing the previous updater created by this method.

        Parameters
        ----------
        speed
            The speed at which to move the submobjects. See :meth:`get_nudge_updater` for details.
        pointwise
            Whether to move the mobject along the vector field. See :meth:`nudge` for details.

        Returns
        -------
        VectorField
            This vector field.

        c                8    |                      |z            S r   )r   )rw   rx   rz   r   s     rH   rZ   z7VectorField.start_submobject_movement.<locals>.<lambda>n  s'    s7L7LJ 8M 8
 8
 rI   )stop_submobject_movementrc   add_updaterr   s    ``rH   start_submobject_movementz%VectorField.start_submobject_movementW  sT    , 	%%'''(
 (
 (
 (
 (
$ 	5666rI   c                H    |                      | j                   d| _        | S )zStops the continuous movement started using :meth:`start_submobject_movement`.

        Returns
        -------
        VectorField
            This vector field.
        N)remove_updaterrc   )rW   s    rH   r   z$VectorField.stop_submobject_movementu  s(     	D8999'+$rI      sampling_rateImage.Imagec                   | j         rt          d          t          t          d         |z            }t          t          d         |z            }t          d         }t          d         }t	          j        ||df          }t	          j        | dz  |dz  |          }t	          j        |dz  | dz  |          }|                    dt          |          f          }|                    t          |          df          }|	                    |d	
          }|	                    |d
           ||ddddd	f<   ||dddddf<   t	          j
        | j        d|          }	t          j        |	dz                      d                    S )a  Generate an image that displays the vector field.

        The color at each position is calculated by passing the positing through a
        series of steps:
        Calculate the vector field function at that position, map that vector to a
        single value using `self.color_scheme` and finally generate a color from
        that value using the color gradient.

        Parameters
        ----------
        sampling_rate
            The stepsize at which pixels get included in the image. Lower values give
            more accurate results, but may take a long time to compute.

        Returns
        -------
        Image.Imgae
            The vector field image.
        zQThere is no point in generating an image if the vector field uses a single color.pixel_heightpixel_widthframe_widthframe_height   r   rM   r   axisN   uint8)r^   
ValueErrorrQ   r   rE   zeroslinspacereshaperO   repeatapply_along_axisrX   r   	fromarrayastype)
rW   r   phpwfwfhpoints_arrayx_arrayy_arrayrP   s
             rH   get_colored_background_imagez(VectorField.get_colored_background_image  s   (  	c   '-788&677M"N#xR,,+rcAgrAvr22+b1frcAgr22//1c'll"344//3w<<"344..!.,,r""" 'QQQ1W 'QQQ1W"4?A|DDs
227;;<<<rI   startendIterable[ParsableManimColor]3Callable[[Sequence[float], float], FloatRGBA_Array]c                Z    t          j        d |D                       d
dfd	}|S )a  
        Generates a gradient of rgbas as a numpy array

        Parameters
        ----------
        start
            start value used for inverse interpolation at :func:`~.inverse_interpolate`
        end
            end value used for inverse interpolation at :func:`~.inverse_interpolate`
        colors
            list of colors to generate the gradient

        Returns
        -------
            function to generate the gradients as numpy arrays representing rgba values
        c                ,    g | ]}t          |          S r[   )r'   ).0cs     rH   
<listcomp>zEVectorField.get_vectorized_rgba_gradient_function.<locals>.<listcomp>  s    (I(I(IQa(I(I(IrI         ?valuesr}   opacityr<   rB   r/   c                P   t          	t          j        |                     }t          j        |dd          }|t	          
          dz
  z  }|                    t                    }t          j        |dz   dt	          
          dz
            }|dz  }|                    d                              t	          |          df          }t          
|         
|         |          }t          j
        |t          j        t	          |          dg|          fd          }|S )Nr   rM   r   r   )r    rE   r_   rN   rO   r   rQ   r   r   r   concatenatefull)r   r   alphasscaled_alphasindicesnext_indicesinter_alphasnew_rgbs	new_rgbasr   rP   r   s            rH   r5   z?VectorField.get_vectorized_rgba_gradient_function.<locals>.func  s   (RXf5E5EFFFWVQ**F"c$ii!m4M#**3//G77Q;3t99q=AAL(1,L'..q11993w<<:KLLL'2WtL1<( (H *,27CMM1#5w??@* * *I rI   )r   )r   r}   r   r<   rB   r/   )rE   r_   )rW   r   r   r>   r5   rP   s    ``  @rH   %get_vectorized_rgba_gradient_functionz1VectorField.get_vectorized_rgba_gradient_function  sY    ,  "x(I(I&(I(I(IJJ	 	 	 	 	 	 	 	 	" rI   )r5   r6   r7   r8   r9   r:   r;   r<   r=   r<   r>   r?   )r5   rf   rg   rh   rB   rf   )r5   rf   rm   r<   rB   rf   )rq   r   )rM   rM   F)
rw   r   rx   r<   ry   rQ   rz   r{   rB   r   )rx   r<   ry   rQ   rz   r{   rB   r   )rM   F)r   r<   rz   r{   rB   r   )r   r<   rz   r{   rB   r   )rB   r   )r   )r   rQ   rB   r   )r   r<   r   r<   r>   r   rB   r   )__name__
__module____qualname____doc__r3   r]   staticmethodrl   rp   rv   r   r   r   r   r   r   r   __classcell__re   s   @rH   r   r   :   s        8 ,0;?()()/J-, -, -, -, -, -, -,^ 0 0 0 \0* "* "* "* \"*HQ Q Q Q& S S S S Sn 	    > P P P P P2     <
 
 
 
&= &= &= &= &=P) ) ) ) ) ) ) )rI   r   c                  H     e Zd ZdZddddeddddd ddfd" fdZd#d!Z xZS )$r   ah  A :class:`VectorField` represented by a set of change vectors.

    Vector fields are always based on a function defining the :class:`~.Vector` at every position.
    The values of this functions is displayed as a grid of vectors.
    By default the color of each vector is determined by it's magnitude.
    Other color schemes can be used however.

    Parameters
    ----------
    func
        The function defining the rate of change at every position of the vector field.
    color
        The color of the vector field. If set, position-specific coloring is disabled.
    color_scheme
        A function mapping a vector to a single value. This value gives the position in the color gradient defined using `min_color_scheme_value`, `max_color_scheme_value` and `colors`.
    min_color_scheme_value
        The value of the color_scheme function to be mapped to the first color in `colors`. Lower values also result in the first color of the gradient.
    max_color_scheme_value
        The value of the color_scheme function to be mapped to the last color in `colors`. Higher values also result in the last color of the gradient.
    colors
        The colors defining the color gradient of the vector field.
    x_range
        A sequence of x_min, x_max, delta_x
    y_range
        A sequence of y_min, y_max, delta_y
    z_range
        A sequence of z_min, z_max, delta_z
    three_dimensions
        Enables three_dimensions. Default set to False, automatically turns True if
        z_range is not None.
    length_func
        The function determining the displayed size of the vectors. The actual size
        of the vector is passed, the returned value will be used as display size for the
        vector. By default this is used to cap the displayed size of vectors to reduce the clutter.
    opacity
        The opacity of the arrows.
    vector_config
        Additional arguments to be passed to the :class:`~.Vector` constructor
    kwargs
        Additional arguments to be passed to the :class:`~.VGroup` constructor

    Examples
    --------

    .. manim:: BasicUsage
        :save_last_frame:

        class BasicUsage(Scene):
            def construct(self):
                func = lambda pos: ((pos[0] * UR + pos[1] * LEFT) - pos) / 3
                self.add(ArrowVectorField(func))

    .. manim:: SizingAndSpacing

        class SizingAndSpacing(Scene):
            def construct(self):
                func = lambda pos: np.sin(pos[0] / 2) * UR + np.cos(pos[1] / 2) * LEFT
                vf = ArrowVectorField(func, x_range=[-7, 7, 1])
                self.add(vf)
                self.wait()

                length_func = lambda x: x / 3
                vf2 = ArrowVectorField(func, x_range=[-7, 7, 1], length_func=length_func)
                self.play(vf.animate.become(vf2))
                self.wait()

    .. manim:: Coloring
        :save_last_frame:

        class Coloring(Scene):
            def construct(self):
                func = lambda pos: pos - LEFT * 5
                colors = [RED, YELLOW, BLUE, DARK_GRAY]
                min_radius = Circle(radius=2, color=colors[0]).shift(LEFT * 5)
                max_radius = Circle(radius=10, color=colors[-1]).shift(LEFT * 5)
                vf = ArrowVectorField(
                    func, min_color_scheme_value=2, max_color_scheme_value=10, colors=colors
                )
                self.add(vf, min_radius, max_radius)

    Nr   r   Fc                &    dt          |           z  S )Ng?r+   )rG   s    rH   rZ   zArrowVectorField.<lambda>6  s    TGDMM=Q rI   r   r5   rf   r7   r8   r9   $Callable[[np.ndarray], float] | Noner;   r<   r=   r>   r?   x_ranger}   y_rangez_rangethree_dimensionsr{   length_funcCallable[[float], float]r   vector_configdict | Nonec                    |p:t          t          d          dz            t          t          d         dz            g _        |p:t          t          d          dz            t          t          d         dz            g _         j         j        g _        |
s|	r7|	p j                                         _         xj         j        gz  c_        n xj        ddggz  c_        t          t           j                            D ]b}t           j        |                   dk    r j        |xx         dgz  cc<    j        |         dxx          j        |         d         z  cc<   c j        \   _         _         _         t                      j        ||||||fi | | _        | _        |i }| _        | _        t!          j         j         }t!          j         j         }t!          j         j         }	  j         fdt'          j        |||	          D                                     j                   d S )Nr   r   r   r   r   rM   c                ~    g | ]9\  }}}                     |t          z  |t          z  z   |t          z  z             :S r[   )
get_vectorr   r   r   )r   xyzrW   s       rH   r   z-ArrowVectorField.__init__.<locals>.<listcomp>g  sQ       Aq! E	AF 2QW <==  rI   )r   r   r
   r   r   rangescopyr   r   rO   r\   r]   r   r   r   r5   rE   arangeadditproductset_opacity)rW   r5   r7   r9   r;   r=   r>   r   r   r   r   r   r   r   rd   ire   s   `               rH   r]   zArrowVectorField.__init__(  sw   &  
6-((1,--&*++#
  
6.))A-..'!+,,#
 |T\2 	$w 	$"9dl&7&7&9&9DLKKDL>)KKKKKQF8#KKs4;''(( 	3 	3A4;q>""a''A3%'KN1Q!2237;0dlDL""	
 	
 	
 	
 	
 ' M*	)T\*)T\*)T\*   !z'7GDD  	
 	
 	&&&&&rI   pointrh   c                   t          j        |                     |                    }t           j                            |          }|dk    r||                     |          |z  z  }t          |fi | j        }|                    |           | j	        r|
                    | j                   n(|
                    |                     |                     |S )aG  Creates a vector in the vector field.

        The created vector is based on the function of the vector field and is
        rooted in the given point. Color and length fit the specifications of
        this vector field.

        Parameters
        ----------
        point
            The root point of the vector.

        r   )rE   r_   r5   rF   rG   r   r   r   r   r^   	set_colorr7   ra   )rW   r   outputrG   vects        rH   r   zArrowVectorField.get_vectorn  s     $))E**++y~~f%%199d&&t,,t33Ff33 233

5 	5NN4:&&&&NN4,,U33444rI   )r5   rf   r7   r8   r9   r   r;   r<   r=   r<   r>   r?   r   r}   r   r}   r   r}   r   r{   r   r   r   r<   r   r   )r   rh   )r   r   r   r   r3   r]   r   r   r   s   @rH   r   r     s        P Pj ,0=A()()/J#'#'#'!&0Q0Q%)!D' D' D' D' D' D' D'L       rI   r   c                  r     e Zd ZdZddddeddddddddd	dddfd0 fdZ	 	 d1d2d#Zd$dd%eefd3d.Z	d4d/Z
 xZS )5r   a  StreamLines represent the flow of a :class:`VectorField` using the trace of moving agents.

    Vector fields are always based on a function defining the vector at every position.
    The values of this functions is displayed by moving many agents along the vector field
    and showing their trace.

    Parameters
    ----------
    func
        The function defining the rate of change at every position of the vector field.
    color
        The color of the vector field. If set, position-specific coloring is disabled.
    color_scheme
        A function mapping a vector to a single value. This value gives the position in the color gradient defined using `min_color_scheme_value`, `max_color_scheme_value` and `colors`.
    min_color_scheme_value
        The value of the color_scheme function to be mapped to the first color in `colors`. Lower values also result in the first color of the gradient.
    max_color_scheme_value
        The value of the color_scheme function to be mapped to the last color in `colors`. Higher values also result in the last color of the gradient.
    colors
        The colors defining the color gradient of the vector field.
    x_range
        A sequence of x_min, x_max, delta_x
    y_range
        A sequence of y_min, y_max, delta_y
    z_range
        A sequence of z_min, z_max, delta_z
    three_dimensions
        Enables three_dimensions. Default set to False, automatically turns True if
        z_range is not None.
    noise_factor
        The amount by which the starting position of each agent is altered along each axis. Defaults to :code:`delta_y / 2` if not defined.
    n_repeats
        The number of agents generated at each starting point.
    dt
        The factor by which the distance an agent moves per step is stretched. Lower values result in a better approximation of the trajectories in the vector field.
    virtual_time
        The time the agents get to move in the vector field. Higher values therefore result in longer stream lines. However, this whole time gets simulated upon creation.
    max_anchors_per_line
        The maximum number of anchors per line. Lines with more anchors get reduced in complexity, not in length.
    padding
        The distance agents can move out of the generation area before being terminated.
    stroke_width
        The stroke with of the stream lines.
    opacity
        The opacity of the stream lines.

    Examples
    --------

    .. manim:: BasicUsage
        :save_last_frame:

        class BasicUsage(Scene):
            def construct(self):
                func = lambda pos: ((pos[0] * UR + pos[1] * LEFT) - pos) / 3
                self.add(StreamLines(func))

    .. manim:: SpawningAndFlowingArea
        :save_last_frame:

        class SpawningAndFlowingArea(Scene):
            def construct(self):
                func = lambda pos: np.sin(pos[0]) * UR + np.cos(pos[1]) * LEFT + pos / 5
                stream_lines = StreamLines(
                    func, x_range=[-3, 3, 0.2], y_range=[-2, 2, 0.2], padding=1
                )

                spawning_area = Rectangle(width=6, height=4)
                flowing_area = Rectangle(width=8, height=6)
                labels = [Tex("Spawning Area"), Tex("Flowing Area").shift(DOWN * 2.5)]
                for lbl in labels:
                    lbl.add_background_rectangle(opacity=0.6, buff=0.05)

                self.add(stream_lines, spawning_area, flowing_area, *labels)

    Nr   r   FrM   g?r   d   r5   rf   r7   r8   r9   r   r;   r<   r=   r>   r?   r   r}   r   r   r   r{   noise_factorfloat | Nonec           	     	    ! |p:t          t          d          dz            t          t          d         dz            g _        |p:t          t          d          dz            t          t          d         dz            g _         j         j        g _        |
s|	r7|	p j                                         _         xj         j        gz  c_        n xj        ddggz  c_        t          t           j                            D ]b}t           j        |                   dk    r j        |xx         dgz  cc<    j        |         dxx          j        |         d         z  cc<   c j        \   _         _         _         t                      j        ||||||fi | ||n j        d         dz   _        | _        | _        | _        | _        | _         j        dz   t$          j                            d          !t%          j         ! fdt           j                  D                       } fd}t          ||z            dz   } j        sP                                  _        t          d	         t2          j        k    r                     |||           _        |D ],}|g}t          |          D ]=}|d
         }|| ||          z  z   } ||          r n|                    |           >|}|sX t=                                  }||z  |_        tA          dtC          t          |           j        z                      }|"                    |d d |                     j        r$|#                     j$         j        |           n$t          j%        t2          j        k    ro|#                     j        dz             t%          j         fd|j&        D                       }|'                                         ||          d           nt%          j(         j        t%          j        g d          k              r4|#                     fd|)                                D                        n|*                     j                   |#                     j        |            +                    |           .g  j,         _-        d S )Nr   r   r   r   r   rM   c           
     "   g | ]}t          j        j         D ]u}t          j        j         D ]_}t          j        j         D ]I}|z
  t
          z  |z
  t          z  z   |z
  t          z  z   j        	                    d           z  z   J`vS )r   )
rE   r   r   r   r   r   r   r   r   random)r   nr   r   r   
half_noiserngrW   s        rH   r   z(StreamLines.__init__.<locals>.<listcomp>  s     	 	 	
 DL1	 	 DL1	 	 DL1	 	  Z5(z>R'(z>S() #cjjmm34	 	 	 	 	 	rI   c                   | d         j         d         j        z
  k     p| d         j         d         j        z   j         d         z
  k    p| d         j        d         j        z
  k     px| d         j        d         j        z   j        d         z
  k    pK| d         j        d         j        z
  k     p,| d         j        d         j        z   j        d         z
  k    S )Nr   rM   r   )r   paddingr   r   )rk   rW   s    rH   outside_boxz)StreamLines.__init__.<locals>.outside_box(  s    !t|A55 KQ4$,q/DL84<?JJKQ4$,q/DL88K Q4$,q/DL84<?JJK Q4$,q/DL88	K
 Q4$,q/DL84<?JJrI   renderer)r7   widthr   g      @)r  c                t    g | ]4}t           j                                                |                    5S r[   )rE   rF   rG   r5   )r   r   rW   s     rH   r   z(StreamLines.__init__.<locals>.<listcomp>S  s3    SSSe		%(8(899SSSrI   stroke_rgba)name)r   r   r   c                :    g | ]}                     |          S r[   )ra   )r   rk   rW   s     rH   r   z(StreamLines.__init__.<locals>.<listcomp>\  s'    NNNaT..q11NNNrI   )r  r   ).r   r   r
   r   r   r   r   r   r   rO   r\   r]   r   	n_repeatsvirtual_timemax_anchors_per_liner  stroke_widthrE   r   default_rngr_   r^   r   background_imgr   OPENGLr   values_to_rgbasappendr   durationmaxrQ   set_points_smoothly
set_stroker7   r  pointsset_rgba_array_directanyget_anchorscolor_using_background_imager   r   stream_lines)#rW   r5   r7   r9   r;   r=   r>   r   r   r   r   r   r
  rx   r  r  r  r  r   rd   r   start_pointsr  	max_stepsr   r  r   
last_point	new_pointsteplinenormsr   r   re   s#   `                               @@rH   r]   zStreamLines.__init__  sx   2  
6-((1,--&*++#
  
6.))A-..'!+,,#
 |T\2 	$w 	$"9dl&7&7&9&9DLKKDL>)KKKKKQF8#KKs4;''(( 	3 	3A4;q>""a''A3%'KN1Q!2237;0dlDL""	
 	
 	
 	
 	
 )4LL$,q/A:M 	 #($8!(&*
i##A&&x	 	 	 	 	 	
 t~..	 	 	
 
	 	 	 	 	 *++a/	  	"&"C"C"E"EDj!\%888'+'Q'Q**( ($
 " &	 &	EWF9%% ) )#BZ
&dd:.>.>)>>	;y)) Ei((((D 1/1133D 2IDMq#c&kkD,EEFFGGD$$VFFdF^444  N*D,=w       ?l&999OO$*;c*AOBBBHSSSSt{SSS E ..,,UG<<* /    
 vdlbh}}}.E.EEFF ONNNN4;K;K;M;MNNN    99$:MNNNOO$*;WOMMMHHTNNNN/d./rI   	lag_ratiorun_timeCallable[[float], float] | NonerB   r   c                    | j         |dz  t          | j                  z  }fd| j        D             }t	          j        |           t          |d|iS )a  The creation animation of the stream lines.

        The stream lines appear in random order.

        Parameters
        ----------
        lag_ratio
            The lag ratio of the animation.
            If undefined, it will be selected so that the total animation length is 1.5 times the run time of each stream line creation.
        run_time
            The run time of every single stream line creation. The runtime of the whole animation might be longer due to the `lag_ratio`.
            If undefined, the virtual time of the stream lines is used as run time.

        Returns
        -------
        :class:`~.AnimationGroup`
            The creation animation of the stream lines.

        Examples
        --------

        .. manim:: StreamLineCreation

            class StreamLineCreation(Scene):
                def construct(self):
                    func = lambda pos: (pos[0] * UR + pos[1] * LEFT) - pos
                    stream_lines = StreamLines(
                        func,
                        color=YELLOW,
                        x_range=[-7, 7, 1],
                        y_range=[-4, 4, 1],
                        stroke_width=3,
                        virtual_time=1,  # use shorter lines
                        max_anchors_per_line=5,  # better performance with fewer anchors
                    )
                    self.play(stream_lines.create())  # uses virtual_time as run_time
                    self.wait()

        Nr   c                .    g | ]}t          |fd iS r%  r   )r   r"  rd   r%  s     rH   r   z&StreamLines.create.<locals>.<listcomp>  s;     
 
 
:>F455(5f55
 
 
rI   r$  )r  rO   r   r  r   shuffler   )rW   r$  r%  rd   
animationss     `` rH   createzStreamLines.created  s    Z (H 1s4+;'<'<<I
 
 
 
 
BFBS
 
 

 	z"""z?Y???rI   Tg333333?warm_up
flow_speed
time_width	rate_funcr   line_animation_classtype[ShowPassingFlash]Nonec                     j         D ]}|j        z  } ||f|||d||_        |j                                         t	          j                     j        z  |_        |r|xj        dz  c_                             |j        j                    fd}	 	                    |	           |	 _
         _        | _        dS )a  Animates the stream lines using an updater.

        The stream lines will continuously flow

        Parameters
        ----------
        warm_up
            If `True` the animation is initialized line by line. Otherwise it starts with all lines shown.
        flow_speed
            At `flow_speed=1` the distance the flow moves per second is equal to the magnitude of the vector field along its path. The speed value scales the speed of this flow.
        time_width
            The proportion of the stream line shown while being animated
        rate_func
            The rate function of each stream line flashing
        line_animation_class
            The animation class being used

        Examples
        --------

        .. manim:: ContinuousMotion

            class ContinuousMotion(Scene):
                def construct(self):
                    func = lambda pos: np.sin(pos[0] / 2) * UR + np.cos(pos[1] / 2) * LEFT
                    stream_lines = StreamLines(func, stroke_width=3, max_anchors_per_line=30)
                    self.add(stream_lines)
                    stream_lines.start_animation(warm_up=False, flow_speed=1.5)
                    self.wait(stream_lines.virtual_time / stream_lines.flow_speed)

        )r%  r0  r/  r  c                   | j         D ]z}|xj        |z  z  c_        |j        j        k    r|xj        j        z  c_        |j                            t          j        |j        |j        j        z  dd                     {d S )Nr   rM   )r  timer  animr   rE   rN   r%  )rw   rx   r"  r.  rW   s      rH   updaterz,StreamLines.start_animation.<locals>.updater  s    ( U U		R*_,		9 111II!22II	%%bgdi$):L.LaQR&S&STTTT	U UrI   N)r  r  r7  beginr   r  r6  r   mobjectr   flow_animationr.  r/  )
rW   r-  r.  r/  r0  r1  rd   r"  r%  r8  s
   ` `       rH   start_animationzStreamLines.start_animation  s   P % 	( 	(D}z1H,,!#%	 
  DI IOO$*;;DI  		R		HHTY&''''	U 	U 	U 	U 	U 	U 	!!!%$$rI   c                     j         t          d          d } fd} j         j        z  }t          } |d          dz  }|d j        z   z  |z  }dt          d         z  g }                      j                    d _          j        D ]}t          |||	          }	|j
        d
k    rz|                    t          t          |||j
          j        z            |	                                          |j        j                   |j                                         ||j
         j        z  z
  }
|                    t          t          |||
          |	                     t%          | S )a  End the stream line animation smoothly.

        Returns an animation resulting in fully displayed stream lines without a noticeable cut.

        Returns
        -------
        :class:`~.AnimationGroup`
            The animation fading out the running stream animation.

        Raises
        ------
        ValueError
            if no stream line animation is running

        Examples
        --------

        .. manim:: EndAnimation

            class EndAnimation(Scene):
                def construct(self):
                    func = lambda pos: np.sin(pos[0] / 2) * UR + np.cos(pos[1] / 2) * LEFT
                    stream_lines = StreamLines(
                        func, stroke_width=3, max_anchors_per_line=5, virtual_time=1, color=BLUE
                    )
                    self.add(stream_lines)
                    stream_lines.start_animation(warm_up=False, flow_speed=1.5, time_width=0.5)
                    self.wait(1)
                    self.play(stream_lines.end_animation())

        Nz5You have to start the animation before fading it out.c                ~    |dk    r|                      d           d S |dk    r|                      d           d S d S )Nr   )r   rM   )r  )rw   rT   s     rH   hide_and_waitz0StreamLines.end_animation.<locals>.hide_and_wait  sO    zzq)))))!q))))) rI   c                ,   | xj         j        z  z  c_         | j                            t	          | j         | j        j        z  d                     |dk    r:                    | j        j                   | j                                         d S d S rL   )	r6  r.  r7  r   rR   r%  remover:  finish)r"  rT   rx   rW   s     rH   finish_updater_cyclez7StreamLines.end_animation.<locals>.finish_updater_cycle  s    IIdo--III!!#di$)2D&Da"H"HIIIzzDI-...	  """"" zrI   gMbP?i  rM   
frame_rate)r%  r0  r   r)  )r;  r   r  r.  r)   r/  r   r   r  r   r6  r  r   r   rA  r7  r:  rB  r   )rW   r?  rC  max_run_timecreation_rate_funccreation_staring_speedcreation_run_timer+  r"  r,  remaining_timerx   s   `          @rH   end_animationzStreamLines.end_animation  s   @ &TUUU	* 	* 	*	# 	# 	# 	# 	# 	# (4?:*!3!3E!:!:T!AA/03II 	 %%
D/000"% 	 	D*,  F
 yA~~!!+ )&*iZ$/%A  
  	 	 	 DI-...	  """"!-	DO0K!K!!+ 0%3  
  	 	 	 	 z**rI   )r5   rf   r7   r8   r9   r   r;   r<   r=   r<   r>   r?   r   r}   r   r}   r   r}   r   r{   r   r   )NN)r$  r   r%  r&  rB   r   )r-  r{   r.  r<   r/  r<   r0  r   r1  r2  rB   r3  )rB   r   )r   r   r   r   r3   r]   r,  r*   r   r<  rJ  r   r   s   @rH   r   r     s        K K` ,0=A()()/J#'#'#'!&%) -L0 L0 L0 L0 L0 L0 L0` #'486@ 6@ 6@ 6@ 6@t .47GA% A% A% A% A%F]+ ]+ ]+ ]+ ]+ ]+ ]+ ]+rI   r   )Jr   
__future__r   __all__	itertoolsr   r   collections.abcr   r   r	   mathr
   r   typingr   numpyrE   PILr   manim.animation.updaters.updater   manim.mobject.geometry.liner   )manim.mobject.graphing.coordinate_systemsr    r   animation.compositionr   r   animation.creationr   animation.indicationr   	constantsr   r   r   r   mobject.mobjectr    mobject.types.vectorized_mobjectr   mobject.utilsr   utils.bezierr   r    utils.colorr!   r"   r#   r$   r%   r&   r'   r(   utils.rate_functionsr)   r*   utils.simple_functionsr,   manim.typingr-   r.   r/   r0   r1   r3   __annotations__r   r   r   r[   rI   rH   <module>rd     sC   * * * " " " " " "        8 8 8 8 8 8 8 8 8 8                               ? ? ? ? ? ? . . . . . . F F F F F F       > > > > > > > > ' ' ' ' ' ' 3 3 3 3 3 3 4 4 4 4 4 4 4 4 4 4 4 4 % % % % % % 5 5 5 5 5 5 8 8 8 8 8 8 ; ; ; ; ; ; ; ;	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 9 8 8 8 8 8 8 8 , , , , , ,               &,UFC$@  @ @ @ @X X X X X& X X Xvp p p p p{ p p pft+ t+ t+ t+ t++ t+ t+ t+ t+ t+rI   