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

Code before:
    for dim, coord in enumerate(point):
        control_coords = c_c = control_points[:, dim]
        terms = []
        for term_power in range(n, -1, -1):
            outercoeff = choose(n, term_power)
            term = []
            negative = 1
            for subterm_num in range(term_power, -1, -1):
                innercoeff = choose(term_power, subterm_num) * negative
                subterm = (
                    innercoeff * c_c[subterm_num]
                    if term_power > 0
                    else ((innercoeff * c_c[subterm_num]) - coord)
                )
                term.append(subterm)
                negative = -1 if negative > 0 else 1
            terms.append(outercoeff * sum(np.array(term)))
        bezier_polynom = np.polynomial.Polynomial(terms[::-1])
        polynom_roots = bezier_polynom.roots()
        if len(polynom_roots) > 0:
            roots.append(polynom_roots)

    roots = np.around(roots, int(np.log10(1 / round_to)))
    roots = [[root for root in rootlist if root.imag == 0] for rootlist in roots]
    roots = reduce(np.intersect1d, roots)  # Get common roots.
    roots = np.array([r.real for r in roots]).tolist()
    return roots


def point_lies_on_bezier(
    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,
) -> bool:
    """Checks if a given point lies on the bezier curves with the given control points.

    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

Review comment (suggestion):
Not sure what the point of converting it to an array then back to a list is
```suggestion
    roots = [r.real for r in roots]
```

Code after:
            f"Point {point} and Control Points {control_points} have different shapes."
        )

    control_points = np.array(control_points)
    n = len(control_points) - 1

    roots = []
    for dim, coord in enumerate(point):
        control_coords = control_points[:, dim]
        terms = []
        for term_power in range(n, -1, -1):
            outercoeff = choose(n, term_power)
            term = []
            sign = 1
            for subterm_num in range(term_power, -1, -1):
                innercoeff = choose(term_power, subterm_num) * sign
                subterm = innercoeff * control_coords[subterm_num]
                if term_power == 0:
                    subterm -= coord
                term.append(subterm)
                sign *= -1
            terms.append(outercoeff * sum(np.array(term)))
        if all(term == 0 for term in terms):
            # Then both Bezier curve and Point lie on the same plane.
            # Roots will be none, but in this specific instance, we don't need to consider that.
            continue
        bezier_polynom = np.polynomial.Polynomial(terms[::-1])
        polynom_roots = bezier_polynom.roots()
        if len(polynom_roots) > 0:
            polynom_roots = np.around(polynom_roots, int(np.log10(1 / round_to)))
        roots.append(polynom_roots)

    roots = [[root for root in rootlist if root.imag == 0] for rootlist in roots]
    roots = reduce(np.intersect1d, roots)  # Get common roots.
    roots = np.array([r.real for r in roots])
    return roots


def point_lies_on_bezier(
    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,
) -> bool:
    """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