diff --git a/manim/camera/moving_camera.py b/manim/camera/moving_camera.py index 56304064fb..ff7f82be3d 100644 --- a/manim/camera/moving_camera.py +++ b/manim/camera/moving_camera.py @@ -12,13 +12,13 @@ # TODO, think about how to incorporate perspective class CameraFrame(VGroup): CONFIG = { - "width": config["frame_width"], - "height": config["frame_height"], "center": ORIGIN, } def __init__(self, **kwargs): - pass + VGroup.__init__(self, **kwargs) + self.width = config["frame_width"] + self.height = config["frame_height"] class MovingCamera(Camera): diff --git a/manim/camera/three_d_camera.py b/manim/camera/three_d_camera.py index b6ea003134..3fe133d70a 100644 --- a/manim/camera/three_d_camera.py +++ b/manim/camera/three_d_camera.py @@ -29,7 +29,6 @@ class ThreeDCamera(Camera): "light_source_start_point": 9 * DOWN + 7 * LEFT + 10 * OUT, "should_apply_shading": True, "exponential_projection": False, - "max_allowable_norm": 3 * config["frame_width"], } def __init__(self, *args, **kwargs): @@ -43,6 +42,7 @@ def __init__(self, *args, **kwargs): Any keyword argument of Camera. """ Camera.__init__(self, *args, **kwargs) + self.max_allowable_norm = 3 * config["frame_width"] self.phi_tracker = ValueTracker(self.phi) self.theta_tracker = ValueTracker(self.theta) self.distance_tracker = ValueTracker(self.distance) diff --git a/manim/mobject/coordinate_systems.py b/manim/mobject/coordinate_systems.py index d5b60cf302..20b088a3b7 100644 --- a/manim/mobject/coordinate_systems.py +++ b/manim/mobject/coordinate_systems.py @@ -25,13 +25,16 @@ class CoordinateSystem: Abstract class for Axes and NumberPlane """ - CONFIG = { - "dimension": 2, - "x_min": -config["frame_x_radius"], - "x_max": config["frame_x_radius"], - "y_min": -config["frame_y_radius"], - "y_max": config["frame_y_radius"], - } + def __init__(self, dim=2): + self.dimension = dim + if not hasattr(self, 'x_min'): + self.x_min = -config["frame_x_radius"] + if not hasattr(self, 'x_max'): + self.x_max = config["frame_x_radius"] + if not hasattr(self, 'y_min'): + self.y_min = -config["frame_y_radius"] + if not hasattr(self, 'y_max'): + self.y_max = config["frame_y_radius"] def coords_to_point(self, *coords): raise Exception("Not implemented") @@ -130,16 +133,17 @@ class Axes(VGroup, CoordinateSystem): "exclude_zero_from_default_numbers": True, }, "x_axis_config": {}, - "y_axis_config": {"label_direction": LEFT,}, + "y_axis_config": {"label_direction": LEFT}, "center_point": ORIGIN, } def __init__(self, **kwargs): + CoordinateSystem.__init__(self, **kwargs) VGroup.__init__(self, **kwargs) self.x_axis = self.create_axis(self.x_min, self.x_max, self.x_axis_config) self.y_axis = self.create_axis(self.y_min, self.y_max, self.y_axis_config) self.y_axis.rotate(90 * DEGREES, about_point=ORIGIN) - # Add as a separate group incase various other + # Add as a separate group in case various other # mobjects are added to self, as for example in # NumberPlane below self.axes = VGroup(self.x_axis, self.y_axis) @@ -189,11 +193,7 @@ def add_coordinates(self, x_vals=None, y_vals=None): class ThreeDAxes(Axes): CONFIG = { - "dimension": 3, - "x_min": -5.5, - "x_max": 5.5, - "y_min": -5.5, - "y_max": 5.5, + "z_axis_config": {}, "z_min": -3.5, "z_max": 3.5, @@ -203,7 +203,12 @@ class ThreeDAxes(Axes): } def __init__(self, **kwargs): + self.x_min = -5.5 + self.x_max = 5.5 + self.y_min = -5.5 + self.y_max = 5.5 Axes.__init__(self, **kwargs) + self.dimension = 3 z_axis = self.z_axis = self.create_axis( self.z_min, self.z_max, self.z_axis_config ) @@ -245,7 +250,7 @@ class NumberPlane(Axes): "label_direction": DR, "number_scale_val": 0.5, }, - "y_axis_config": {"label_direction": DR,}, + "y_axis_config": {"label_direction": DR}, "background_line_style": { "stroke_color": BLUE_D, "stroke_width": 2, diff --git a/manim/mobject/frame.py b/manim/mobject/frame.py index 489b385737..a1e7695e7c 100644 --- a/manim/mobject/frame.py +++ b/manim/mobject/frame.py @@ -21,9 +21,9 @@ def __init__(self, **kwargs): class FullScreenRectangle(ScreenRectangle): - CONFIG = { - "height": config["frame_height"], - } + def __init__(self, **kwargs): + ScreenRectangle.__init__(self, **kwargs) + self.set_height(config["frame_height"]) class FullScreenFadeRectangle(FullScreenRectangle): diff --git a/manim/mobject/functions.py b/manim/mobject/functions.py index 902966ce4c..8776eaf744 100644 --- a/manim/mobject/functions.py +++ b/manim/mobject/functions.py @@ -80,12 +80,12 @@ def generate_points(self): class FunctionGraph(ParametricFunction): CONFIG = { "color": YELLOW, - "x_min": -config["frame_x_radius"], - "x_max": config["frame_x_radius"], } def __init__(self, function, **kwargs): digest_config(self, kwargs) + self.x_min = -config["frame_x_radius"] + self.x_max = config["frame_x_radius"] self.parametric_function = lambda t: np.array([t, function(t), 0]) ParametricFunction.__init__( self, self.parametric_function, t_min=self.x_min, t_max=self.x_max, **kwargs diff --git a/manim/mobject/mobject.py b/manim/mobject/mobject.py index 242ef42a26..c02476a44c 100644 --- a/manim/mobject/mobject.py +++ b/manim/mobject/mobject.py @@ -15,7 +15,7 @@ from colour import Color import numpy as np -from .. import config +from .. import config, file_writer_config from ..constants import * from ..container import Container from ..utils.color import color_gradient @@ -198,7 +198,7 @@ def show(self, camera=None): def save_image(self, name=None): self.get_image().save( - os.path.join(config["VIDEO_DIR"], (name or str(self)) + ".png") + os.path.join(file_writer_config["video_dir"], (name or str(self)) + ".png") ) def copy(self): diff --git a/manim/mobject/number_line.py b/manim/mobject/number_line.py index 1c148d0729..76c231f3d6 100644 --- a/manim/mobject/number_line.py +++ b/manim/mobject/number_line.py @@ -21,8 +21,6 @@ class NumberLine(Line): CONFIG = { "color": LIGHT_GREY, - "x_min": -config["frame_x_radius"], - "x_max": config["frame_x_radius"], "unit_size": 1, "include_ticks": True, "tick_size": 0.1, @@ -49,6 +47,8 @@ class NumberLine(Line): } def __init__(self, **kwargs): + self.x_min = -config["frame_x_radius"] + self.x_max = config["frame_x_radius"] digest_config(self, kwargs) start = self.unit_size * self.x_min * RIGHT end = self.unit_size * self.x_max * RIGHT @@ -180,11 +180,14 @@ def add_numbers(self, *numbers, **kwargs): class UnitInterval(NumberLine): CONFIG = { - "x_min": 0, - "x_max": 1, "unit_size": 6, "tick_frequency": 0.1, "numbers_with_elongated_ticks": [0, 1], "number_at_center": 0.5, "decimal_number_config": {"num_decimal_places": 1,}, } + + def __init__(self, **kwargs): + NumberLine.__init__(self, **kwargs) + self.x_min = 0 + self.x_max = 1 diff --git a/manim/mobject/svg/drawings.py b/manim/mobject/svg/drawings.py index 869ead4431..dd945363f1 100644 --- a/manim/mobject/svg/drawings.py +++ b/manim/mobject/svg/drawings.py @@ -303,11 +303,11 @@ def __init__(self, **kwargs): class VideoIcon(SVGMobject): CONFIG = { "file_name": "video_icon", - "width": config["frame_width"] / 12.0, } def __init__(self, **kwargs): SVGMobject.__init__(self, **kwargs) + self.width = config["frame_width"] / 12.0 self.center() self.set_width(self.width) self.set_stroke(color=WHITE, width=0) diff --git a/manim/mobject/svg/tex_mobject.py b/manim/mobject/svg/tex_mobject.py index a82c639ac2..1c9b7fed42 100644 --- a/manim/mobject/svg/tex_mobject.py +++ b/manim/mobject/svg/tex_mobject.py @@ -307,7 +307,6 @@ class Title(Tex): CONFIG = { "scale_factor": 1, "include_underline": True, - "underline_width": config["frame_width"] - 2, # This will override underline_width "match_underline_width_to_text": False, "underline_buff": MED_SMALL_BUFF, @@ -315,6 +314,7 @@ class Title(Tex): def __init__(self, *text_parts, **kwargs): Tex.__init__(self, *text_parts, **kwargs) + self.underline_width = config["frame_width"] - 2 self.scale(self.scale_factor) self.to_edge(UP) if self.include_underline: diff --git a/manim/mobject/vector_field.py b/manim/mobject/vector_field.py index f9078b2264..890f01ebbb 100644 --- a/manim/mobject/vector_field.py +++ b/manim/mobject/vector_field.py @@ -41,10 +41,8 @@ def get_colored_background_image( - scalar_field_func, - number_to_rgb_func, - pixel_height=config["pixel_height"], - pixel_width=config["pixel_width"], + scalar_field_func, + number_to_rgb_func, ): ph = config["pixel_height"] pw = config["pixel_width"] @@ -139,10 +137,6 @@ class VectorField(VGroup): CONFIG = { "delta_x": 0.5, "delta_y": 0.5, - "x_min": int(np.floor(-config["frame_width"] / 2)), - "x_max": int(np.ceil(config["frame_width"] / 2)), - "y_min": int(np.floor(-config["frame_height"] / 2)), - "y_max": int(np.ceil(config["frame_height"] / 2)), "min_magnitude": 0, "max_magnitude": 2, "colors": DEFAULT_SCALAR_FIELD_COLORS, @@ -154,6 +148,10 @@ class VectorField(VGroup): def __init__(self, func, **kwargs): VGroup.__init__(self, **kwargs) + self.x_min = int(np.floor(-config["frame_width"] / 2)) + self.x_max = int(np.ceil(config["frame_width"] / 2)) + self.y_min = int(np.floor(-config["frame_height"] / 2)) + self.y_max = int(np.ceil(config["frame_height"] / 2)) self.func = func self.rgb_gradient_function = get_rgb_gradient_function( self.min_magnitude, self.max_magnitude, self.colors, flip_alphas=False diff --git a/manim/scene/three_d_scene.py b/manim/scene/three_d_scene.py index 6f8cfc4f4f..a1b9be8117 100644 --- a/manim/scene/three_d_scene.py +++ b/manim/scene/three_d_scene.py @@ -302,7 +302,7 @@ class SpecialThreeDScene(ThreeDScene): def __init__(self, **kwargs): digest_config(self, kwargs) - if self.camera_config["pixel_width"] == config["CAMERA_CONFIG"]["PIXEL_WIDTH"]: + if self.camera_config["pixel_width"] == config["pixel_width"]: config = {} else: config = self.low_quality_config diff --git a/manim/scene/vector_space_scene.py b/manim/scene/vector_space_scene.py index 65bc19eb57..7536c55550 100644 --- a/manim/scene/vector_space_scene.py +++ b/manim/scene/vector_space_scene.py @@ -508,13 +508,6 @@ class LinearTransformationScene(VectorScene): CONFIG = { "include_background_plane": True, "include_foreground_plane": True, - "foreground_plane_kwargs": { - "x_max": config["frame_width"] / 2, - "x_min": -config["frame_width"] / 2, - "y_max": config["frame_width"] / 2, - "y_min": -config["frame_width"] / 2, - "faded_line_ratio": 0, - }, "background_plane_kwargs": { "color": GREY, "axis_config": { @@ -537,6 +530,16 @@ class LinearTransformationScene(VectorScene): "t_matrix": [[3, 0], [1, 2]], } + def __init__(self, **kwargs): + VectorScene.__init__(self, **kwargs) + self.foreground_plane_kwargs = { + "x_max": config["frame_width"] / 2, + "x_min": -config["frame_width"] / 2, + "y_max": config["frame_width"] / 2, + "y_min": -config["frame_width"] / 2, + "faded_line_ratio": 0, + } + def setup(self): # The has_already_setup attr is to not break all the old Scenes if hasattr(self, "has_already_setup"): diff --git a/tests/test_coordinate_system.py b/tests/test_coordinate_system.py new file mode 100644 index 0000000000..2c8bbd9b95 --- /dev/null +++ b/tests/test_coordinate_system.py @@ -0,0 +1,38 @@ +import pytest +import numpy as np +from manim import CoordinateSystem as CS +from manim import Axes, ThreeDAxes, NumberPlane, ComplexPlane +from manim import config, tempconfig, ORIGIN, LEFT + + +def test_initial_config(): + """Check that all attributes are defined properly from the config.""" + cs = CS() + assert cs.x_min == -config['frame_x_radius'] + assert cs.x_max == config['frame_x_radius'] + assert cs.y_min == -config['frame_y_radius'] + assert cs.y_max == config['frame_y_radius'] + + ax = Axes() + assert np.allclose(ax.center_point, ORIGIN) + assert np.allclose(ax.y_axis_config['label_direction'], LEFT) + + with tempconfig({'frame_x_radius': 100, 'frame_y_radius': 200}): + cs = CS() + assert cs.x_min == -100 + assert cs.x_max == 100 + assert cs.y_min == -200 + assert cs.y_max == 200 + +def test_dimension(): + """Check that objects have the correct dimension.""" + assert Axes().dimension == 2 + assert NumberPlane().dimension == 2 + assert ComplexPlane().dimension == 2 + assert ThreeDAxes().dimension == 3 + + +def test_abstract_base_class(): + """Check that CoordinateSystem has some abstract methods.""" + with pytest.raises(Exception): + CS().get_axes() diff --git a/tests/test_graphical_units/test_graph.py b/tests/test_graphical_units/test_graph.py index 5dfac1841c..9b14f5b3f6 100644 --- a/tests/test_graphical_units/test_graph.py +++ b/tests/test_graphical_units/test_graph.py @@ -7,10 +7,6 @@ class PlotFunctions(GraphScene): CONFIG = { - "x_min": -10, - "x_max": 10.3, - "y_min": -1.5, - "y_max": 1.5, "graph_origin": ORIGIN, "function_color": RED, "axes_color": GREEN, @@ -18,6 +14,11 @@ class PlotFunctions(GraphScene): } def construct(self): + self.x_min = -10 + self.x_max = 10.3 + self.y_min = -1.5 + self.y_max = 1.5 + constants.TEX_TEMPLATE = TexTemplate() self.setup_axes() f = self.get_graph(lambda x: x ** 2)