Repository: ManimCommunity/manim
File: manim/utils/bezier.py (Python)

Code before:
    Tm = bezier([h0 - a0, h1 - h0, a1 - h1])(t_mid)

    # Intersection between tangent lines at end points
    # and tangent in the middle
    i0 = find_intersection(a0, T0, mid, Tm)
    i1 = find_intersection(a1, T1, mid, Tm)

    m, n = np.shape(a0)
    result = np.zeros((6 * m, n))
    result[0::6] = a0
    result[1::6] = i0
    result[2::6] = mid
    result[3::6] = mid
    result[4::6] = i1
    result[5::6] = a1
    return result


def is_closed(points: typing.Tuple[np.ndarray, np.ndarray]) -> bool:
    return np.allclose(points[0], points[-1])


def bez_params_from_point(
    point: typing.Iterable[typing.Union[float, int]],
    control_points: typing.Iterable[typing.Iterable[typing.Union[float, int]]],
) -> list[float]:
    """Obtains the parameter corresponding to a given point
    for a given bezier curve.

    Parameters
    ----------
    point (typing.Iterable[float])
        The Cartesian Coordinates of the point whose parameter
        should be obtained.

    control_points (typing.Iterable[typing.Iterable[float]])
        The Cartesian Coordinates of the ordered control
        points of the bezier curve on which the point may
        or may not lie.

    Returns
    -------
        list[float]
            List containing possible parameters 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.
    """
    assert all(np.shape(point) == np.shape(c_p) for c_p in control_points)

Review comment (suggestion):
Using `list[...]` is only supported in 3.9+
```suggestion
) -> typing.List[float]:
```

Code after:
    i0 = find_intersection(a0, T0, mid, Tm)
    i1 = find_intersection(a1, T1, mid, Tm)

    m, n = np.shape(a0)
    result = np.zeros((6 * m, n))
    result[0::6] = a0
    result[1::6] = i0
    result[2::6] = mid
    result[3::6] = mid
    result[4::6] = i1
    result[5::6] = a1
    return result


def is_closed(points: typing.Tuple[np.ndarray, np.ndarray]) -> bool:
    return np.allclose(points[0], points[-1])


def proportions_along_bezier_curve_for_point(
    point: typing.Iterable[typing.Union[float, int]],
    control_points: typing.Iterable[typing.Iterable[typing.Union[float, int]]],
    round_to: typing.Optional[typing.Union[float, int]] = 1e-6,
) -> np.ndarray:
    """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