Repository: ManimCommunity/manim
File: manim/mobject/functions.py (Python)

Code before:
        for t1, t2 in zip(boundary_times[0::2], boundary_times[1::2]):
            t_range = np.array([*np.arange(t1, t2, self.t_step), t2])
            points = np.array([self.function(t) for t in t_range])
            self.start_new_path(points[0])
            self.add_points_as_corners(points[1:])
        if self.use_smoothing:
            # TODO: not in line with upstream, approx_smooth does not exist
            self.make_smooth()
        return self

    init_points = generate_points


class FunctionGraph(ParametricFunction):
    """A parametric curve.

    Examples
    --------
    .. manim:: ExampleFunctionGraph
        :save_last_frame:

        class ExampleFunctionGraph(Scene):
            def construct(self):
                parametricFunction1 = lambda t: np.cos(t)+0.5*np.cos(7*t)+(1/7)*np.cos(14*t)
                parametricFunction2 = lambda t: np.sin(t)+0.5*np.sin(7*t)+(1/7)*np.sin(14*t)
                parametricFunction3 = lambda t: np.sin(t)+0.5*np.sin(7*t)+(1/7)*np.sin(14*t)
                self.add(FunctionGraph(parametricFunction1,color=RED))
                self.add(FunctionGraph(parametricFunction2,color=BLUE))
                self.add(FunctionGraph(parametricFunction3,color=GREEN).move_to([0,1,0]))
    """

    def __init__(self, function, x_range=None, color=YELLOW, **kwargs):

        if x_range is None:
            x_range = np.array([-config["frame_x_radius"], config["frame_x_radius"]])

        self.x_range = x_range
        self.parametric_function = lambda t: np.array([t, function(t), 0])
        self.function = function
        super().__init__(self.parametric_function, self.x_range, color=color, **kwargs)

    def get_function(self):
        return self.function

    def get_point_from_function(self, x):
        return self.parametric_function(x)


Review comment (suggestion):
To differentiate func_3 from func_2 slightly, adding in an `x_range` parameter ([-4, 4] ?) would be nice.

Code after:
        for t1, t2 in zip(boundary_times[0::2], boundary_times[1::2]):
            t_range = np.array([*np.arange(t1, t2, self.t_step), t2])
            points = np.array([self.function(t) for t in t_range])
            self.start_new_path(points[0])
            self.add_points_as_corners(points[1:])
        if self.use_smoothing:
            # TODO: not in line with upstream, approx_smooth does not exist
            self.make_smooth()
        return self

    init_points = generate_points


class FunctionGraph(ParametricFunction):
    """A :class:`ParametricFunction` that spans the length of the scene by default.

    Examples
    --------
    .. manim:: ExampleFunctionGraph
        :save_last_frame:

        class ExampleFunctionGraph(Scene):
            def construct(self):
                cos_func = FunctionGraph(
                    lambda t: np.cos(t) + 0.5 * np.cos(7 * t) + (1 / 7) * np.cos(14 * t),
                    color=RED,
                )

                sin_func_1 = FunctionGraph(
                    lambda t: np.sin(t) + 0.5 * np.sin(7 * t) + (1 / 7) * np.sin(14 * t),
                    color=BLUE,
                )

                sin_func_2 = FunctionGraph(
                    lambda t: np.sin(t) + 0.5 * np.sin(7 * t) + (1 / 7) * np.sin(14 * t),
                    x_range=[-4, 4],
                    color=GREEN,
                ).move_to([0, 1, 0])

                self.add(cos_func, sin_func_1, sin_func_2)
    """

    def __init__(self, function, x_range=None, color=YELLOW, **kwargs):

        if x_range is None:
            x_range = np.array([-config["frame_x_radius"], config["frame_x_radius"]])

        self.x_range = x_range
        self.parametric_function = lambda t: np.array([t, function(t), 0])
        self.function = function
        super().__init__(self.parametric_function, self.x_range, color=color, **kwargs)