2018-03-31 18:31:56 -07:00
|
|
|
import numpy as np
|
2019-02-07 10:13:12 -08:00
|
|
|
import numbers
|
2018-03-31 18:31:56 -07:00
|
|
|
|
2018-12-24 12:37:51 -08:00
|
|
|
from manimlib.constants import *
|
|
|
|
from manimlib.mobject.functions import ParametricFunction
|
|
|
|
from manimlib.mobject.geometry import Arrow
|
|
|
|
from manimlib.mobject.geometry import Line
|
|
|
|
from manimlib.mobject.number_line import NumberLine
|
|
|
|
from manimlib.mobject.svg.tex_mobject import TexMobject
|
|
|
|
from manimlib.mobject.types.vectorized_mobject import VGroup
|
2019-02-06 21:32:42 -08:00
|
|
|
from manimlib.utils.config_ops import merge_dicts_recursively
|
2019-02-06 21:16:26 -08:00
|
|
|
from manimlib.utils.simple_functions import binary_search
|
2018-12-24 12:37:51 -08:00
|
|
|
from manimlib.utils.space_ops import angle_of_vector
|
2018-03-31 18:31:56 -07:00
|
|
|
|
2018-04-06 13:58:59 -07:00
|
|
|
# TODO: There should be much more code reuse between Axes, NumberPlane and GraphScene
|
|
|
|
|
2018-03-31 18:31:56 -07:00
|
|
|
|
2019-02-06 21:16:26 -08:00
|
|
|
class CoordinateSystem():
|
|
|
|
"""
|
|
|
|
Abstract class for Axes and NumberPlane
|
|
|
|
"""
|
|
|
|
CONFIG = {
|
|
|
|
"dimension": 2,
|
|
|
|
"x_min": -FRAME_X_RADIUS,
|
|
|
|
"x_max": FRAME_X_RADIUS,
|
|
|
|
"y_min": -FRAME_Y_RADIUS,
|
|
|
|
"y_max": FRAME_Y_RADIUS,
|
|
|
|
}
|
|
|
|
|
|
|
|
def coords_to_point(self, *coords):
|
|
|
|
raise Exception("Not implemented")
|
|
|
|
|
|
|
|
def point_to_coords(self, point):
|
|
|
|
raise Exception("Not implemented")
|
|
|
|
|
2019-04-09 18:51:18 -07:00
|
|
|
def c2p(self, *coords):
|
|
|
|
"""Abbreviation for coords_to_point"""
|
|
|
|
return self.coords_to_point(*coords)
|
|
|
|
|
|
|
|
def p2c(self, point):
|
|
|
|
"""Abbreviation for point_to_coords"""
|
|
|
|
return self.point_to_coords(point)
|
|
|
|
|
2019-02-06 21:16:26 -08:00
|
|
|
def get_axes(self):
|
|
|
|
raise Exception("Not implemented")
|
|
|
|
|
|
|
|
def get_axis(self, index):
|
|
|
|
return self.get_axes()[index]
|
|
|
|
|
|
|
|
def get_x_axis(self):
|
|
|
|
return self.get_axis(0)
|
|
|
|
|
|
|
|
def get_y_axis(self):
|
|
|
|
return self.get_axis(1)
|
|
|
|
|
|
|
|
def get_z_axis(self):
|
|
|
|
return self.get_axis(2)
|
|
|
|
|
2019-04-06 14:00:52 -07:00
|
|
|
def get_x_axis_label(self, label_tex, edge=RIGHT, direction=DL, **kwargs):
|
|
|
|
return self.get_axis_label(
|
|
|
|
label_tex, self.get_x_axis(),
|
|
|
|
edge, direction, **kwargs
|
|
|
|
)
|
|
|
|
|
|
|
|
def get_y_axis_label(self, label_tex, edge=UP, direction=DR, **kwargs):
|
|
|
|
return self.get_axis_label(
|
|
|
|
label_tex, self.get_y_axis(),
|
|
|
|
edge, direction, **kwargs
|
|
|
|
)
|
|
|
|
|
|
|
|
def get_axis_label(self, label_tex, axis, edge, direction, buff=MED_SMALL_BUFF):
|
|
|
|
label = TexMobject(label_tex)
|
|
|
|
label.next_to(
|
|
|
|
axis.get_edge_center(edge), direction,
|
|
|
|
buff=buff
|
|
|
|
)
|
|
|
|
label.shift_onto_screen(buff=MED_SMALL_BUFF)
|
|
|
|
return label
|
|
|
|
|
|
|
|
def get_axis_labels(self, x_label_tex="x", y_label_tex="y"):
|
|
|
|
self.axis_labels = VGroup(
|
|
|
|
self.get_x_axis_label(x_label_tex),
|
|
|
|
self.get_y_axis_label(y_label_tex),
|
|
|
|
)
|
|
|
|
return self.axis_labels
|
|
|
|
|
2019-02-06 21:16:26 -08:00
|
|
|
def get_graph(self, function, **kwargs):
|
|
|
|
x_min = kwargs.pop("x_min", self.x_min)
|
|
|
|
x_max = kwargs.pop("x_max", self.x_max)
|
|
|
|
graph = ParametricFunction(
|
|
|
|
lambda t: self.coords_to_point(t, function(t)),
|
|
|
|
t_min=x_min,
|
|
|
|
t_max=x_max,
|
|
|
|
**kwargs
|
|
|
|
)
|
|
|
|
graph.underlying_function = function
|
|
|
|
return graph
|
|
|
|
|
|
|
|
def get_parametric_curve(self, function, **kwargs):
|
|
|
|
dim = self.dimension
|
|
|
|
graph = ParametricFunction(
|
|
|
|
lambda t: self.coords_to_point(
|
|
|
|
*function(t)[:dim]
|
|
|
|
),
|
|
|
|
**kwargs
|
|
|
|
)
|
|
|
|
graph.underlying_function = function
|
|
|
|
return graph
|
|
|
|
|
|
|
|
def input_to_graph_point(self, x, graph):
|
2020-02-23 22:56:50 +00:00
|
|
|
alpha = binary_search(
|
|
|
|
function=lambda a: self.x_axis.p2n(
|
|
|
|
graph.point_from_proportion(a)
|
|
|
|
),
|
|
|
|
target=x,
|
|
|
|
lower_bound=self.x_min,
|
|
|
|
upper_bound=self.x_max,
|
|
|
|
)
|
|
|
|
if alpha is not None:
|
|
|
|
return graph.point_from_proportion(alpha)
|
2019-02-06 21:16:26 -08:00
|
|
|
else:
|
2020-02-23 22:56:50 +00:00
|
|
|
return None
|
2019-02-06 21:16:26 -08:00
|
|
|
|
|
|
|
|
|
|
|
class Axes(VGroup, CoordinateSystem):
|
2018-03-31 18:31:56 -07:00
|
|
|
CONFIG = {
|
2020-01-15 15:40:30 -08:00
|
|
|
"axis_config": {
|
2018-04-06 13:58:59 -07:00
|
|
|
"color": LIGHT_GREY,
|
|
|
|
"include_tip": True,
|
2019-02-11 22:14:00 -08:00
|
|
|
"exclude_zero_from_default_numbers": True,
|
2018-03-31 18:31:56 -07:00
|
|
|
},
|
2018-04-06 13:58:59 -07:00
|
|
|
"x_axis_config": {},
|
2018-06-15 13:54:21 -07:00
|
|
|
"y_axis_config": {
|
|
|
|
"label_direction": LEFT,
|
|
|
|
},
|
2019-02-06 21:16:26 -08:00
|
|
|
"center_point": ORIGIN,
|
2018-03-31 18:31:56 -07:00
|
|
|
}
|
2018-04-06 13:58:59 -07:00
|
|
|
|
2018-03-31 18:31:56 -07:00
|
|
|
def __init__(self, **kwargs):
|
|
|
|
VGroup.__init__(self, **kwargs)
|
2019-02-06 21:16:26 -08:00
|
|
|
self.x_axis = self.create_axis(
|
2019-02-04 14:12:49 -08:00
|
|
|
self.x_min, self.x_max, self.x_axis_config
|
|
|
|
)
|
2019-02-06 21:16:26 -08:00
|
|
|
self.y_axis = self.create_axis(
|
2019-02-04 14:12:49 -08:00
|
|
|
self.y_min, self.y_max, self.y_axis_config
|
|
|
|
)
|
2019-01-16 11:08:54 -08:00
|
|
|
self.y_axis.rotate(90 * DEGREES, about_point=ORIGIN)
|
2019-02-06 21:16:26 -08:00
|
|
|
# Add as a separate group incase various other
|
|
|
|
# mobjects are added to self, as for example in
|
|
|
|
# NumberPlane below
|
|
|
|
self.axes = VGroup(self.x_axis, self.y_axis)
|
|
|
|
self.add(*self.axes)
|
|
|
|
self.shift(self.center_point)
|
2018-03-31 18:31:56 -07:00
|
|
|
|
2019-02-06 21:16:26 -08:00
|
|
|
def create_axis(self, min_val, max_val, axis_config):
|
2019-02-06 21:32:42 -08:00
|
|
|
new_config = merge_dicts_recursively(
|
2020-01-15 15:40:30 -08:00
|
|
|
self.axis_config,
|
2019-02-06 21:32:42 -08:00
|
|
|
{"x_min": min_val, "x_max": max_val},
|
|
|
|
axis_config,
|
|
|
|
)
|
2019-02-04 14:12:49 -08:00
|
|
|
return NumberLine(**new_config)
|
|
|
|
|
2018-08-27 16:31:05 -07:00
|
|
|
def coords_to_point(self, *coords):
|
2018-03-31 18:31:56 -07:00
|
|
|
origin = self.x_axis.number_to_point(0)
|
2018-08-27 16:31:05 -07:00
|
|
|
result = np.array(origin)
|
2019-02-06 21:16:26 -08:00
|
|
|
for axis, coord in zip(self.get_axes(), coords):
|
2018-08-27 16:31:05 -07:00
|
|
|
result += (axis.number_to_point(coord) - origin)
|
|
|
|
return result
|
2018-03-31 18:31:56 -07:00
|
|
|
|
2019-05-27 19:47:57 -07:00
|
|
|
def c2p(self, *coords):
|
|
|
|
return self.coords_to_point(*coords)
|
|
|
|
|
2018-03-31 18:31:56 -07:00
|
|
|
def point_to_coords(self, point):
|
2018-08-20 15:49:07 -07:00
|
|
|
return tuple([
|
|
|
|
axis.point_to_number(point)
|
2019-02-06 21:16:26 -08:00
|
|
|
for axis in self.get_axes()
|
2018-08-20 15:49:07 -07:00
|
|
|
])
|
2018-03-31 18:31:56 -07:00
|
|
|
|
2019-05-27 19:47:57 -07:00
|
|
|
def p2c(self, point):
|
|
|
|
return self.point_to_coords(point)
|
|
|
|
|
2019-02-06 21:16:26 -08:00
|
|
|
def get_axes(self):
|
|
|
|
return self.axes
|
2018-03-31 18:31:56 -07:00
|
|
|
|
2019-02-11 22:14:00 -08:00
|
|
|
def get_coordinate_labels(self, x_vals=None, y_vals=None):
|
2019-11-12 11:55:19 -08:00
|
|
|
if x_vals is None:
|
|
|
|
x_vals = []
|
|
|
|
if y_vals is None:
|
|
|
|
y_vals = []
|
2019-02-11 22:14:00 -08:00
|
|
|
x_mobs = self.get_x_axis().get_number_mobjects(*x_vals)
|
|
|
|
y_mobs = self.get_y_axis().get_number_mobjects(*y_vals)
|
|
|
|
|
|
|
|
self.coordinate_labels = VGroup(x_mobs, y_mobs)
|
|
|
|
return self.coordinate_labels
|
|
|
|
|
|
|
|
def add_coordinates(self, x_vals=None, y_vals=None):
|
|
|
|
self.add(self.get_coordinate_labels(x_vals, y_vals))
|
|
|
|
return self
|
|
|
|
|
2018-04-06 13:58:59 -07:00
|
|
|
|
2018-03-31 18:31:56 -07:00
|
|
|
class ThreeDAxes(Axes):
|
|
|
|
CONFIG = {
|
2019-02-06 21:16:26 -08:00
|
|
|
"dimension": 3,
|
2018-04-06 13:58:59 -07:00
|
|
|
"x_min": -5.5,
|
|
|
|
"x_max": 5.5,
|
2018-08-20 15:49:07 -07:00
|
|
|
"y_min": -5.5,
|
|
|
|
"y_max": 5.5,
|
|
|
|
"z_axis_config": {},
|
|
|
|
"z_min": -3.5,
|
|
|
|
"z_max": 3.5,
|
|
|
|
"z_normal": DOWN,
|
|
|
|
"num_axis_pieces": 20,
|
|
|
|
"light_source": 9 * DOWN + 7 * LEFT + 10 * OUT,
|
2018-03-31 18:31:56 -07:00
|
|
|
}
|
|
|
|
|
2018-08-20 15:49:07 -07:00
|
|
|
def __init__(self, **kwargs):
|
|
|
|
Axes.__init__(self, **kwargs)
|
2019-02-06 21:16:26 -08:00
|
|
|
z_axis = self.z_axis = self.create_axis(
|
2018-08-20 15:49:07 -07:00
|
|
|
self.z_min, self.z_max, self.z_axis_config
|
|
|
|
)
|
|
|
|
z_axis.rotate(-np.pi / 2, UP, about_point=ORIGIN)
|
|
|
|
z_axis.rotate(
|
|
|
|
angle_of_vector(self.z_normal), OUT,
|
|
|
|
about_point=ORIGIN
|
|
|
|
)
|
2019-02-11 15:48:44 -08:00
|
|
|
self.axes.add(z_axis)
|
2018-08-20 15:49:07 -07:00
|
|
|
self.add(z_axis)
|
|
|
|
|
|
|
|
self.add_3d_pieces()
|
|
|
|
self.set_axis_shading()
|
|
|
|
|
|
|
|
def add_3d_pieces(self):
|
2019-02-06 21:16:26 -08:00
|
|
|
for axis in self.axes:
|
2018-08-27 16:31:05 -07:00
|
|
|
axis.pieces = VGroup(
|
2019-02-06 21:16:26 -08:00
|
|
|
*axis.get_pieces(self.num_axis_pieces)
|
2018-08-27 16:31:05 -07:00
|
|
|
)
|
|
|
|
axis.add(axis.pieces)
|
2019-02-06 21:16:26 -08:00
|
|
|
axis.set_stroke(width=0, family=False)
|
2018-09-27 17:36:19 -07:00
|
|
|
axis.set_shade_in_3d(True)
|
2018-08-20 15:49:07 -07:00
|
|
|
|
|
|
|
def set_axis_shading(self):
|
|
|
|
def make_func(axis):
|
|
|
|
vect = self.light_source
|
|
|
|
return lambda: (
|
|
|
|
axis.get_edge_center(-vect),
|
|
|
|
axis.get_edge_center(vect),
|
|
|
|
)
|
|
|
|
for axis in self:
|
|
|
|
for submob in axis.family_members_with_points():
|
|
|
|
submob.get_gradient_start_and_end_points = make_func(axis)
|
|
|
|
submob.get_unit_normal = lambda a: np.ones(3)
|
|
|
|
submob.set_sheen(0.2)
|
|
|
|
|
2018-04-06 13:58:59 -07:00
|
|
|
|
2019-02-06 21:16:26 -08:00
|
|
|
class NumberPlane(Axes):
|
2018-03-31 18:31:56 -07:00
|
|
|
CONFIG = {
|
2019-02-06 21:16:26 -08:00
|
|
|
"axis_config": {
|
|
|
|
"stroke_color": WHITE,
|
|
|
|
"stroke_width": 2,
|
|
|
|
"include_ticks": False,
|
|
|
|
"include_tip": False,
|
|
|
|
"line_to_number_buff": SMALL_BUFF,
|
|
|
|
"label_direction": DR,
|
|
|
|
"number_scale_val": 0.5,
|
|
|
|
},
|
|
|
|
"y_axis_config": {
|
|
|
|
"label_direction": DR,
|
|
|
|
},
|
|
|
|
"background_line_style": {
|
|
|
|
"stroke_color": BLUE_D,
|
|
|
|
"stroke_width": 2,
|
2019-02-07 10:13:12 -08:00
|
|
|
"stroke_opacity": 1,
|
2019-02-06 21:16:26 -08:00
|
|
|
},
|
|
|
|
# Defaults to a faded version of line_config
|
|
|
|
"faded_line_style": None,
|
2018-04-06 13:58:59 -07:00
|
|
|
"x_line_frequency": 1,
|
|
|
|
"y_line_frequency": 1,
|
2019-02-06 21:16:26 -08:00
|
|
|
"faded_line_ratio": 1,
|
2018-04-06 13:58:59 -07:00
|
|
|
"make_smooth_after_applying_functions": True,
|
2018-03-31 18:31:56 -07:00
|
|
|
}
|
2018-04-06 13:58:59 -07:00
|
|
|
|
2019-02-06 21:16:26 -08:00
|
|
|
def __init__(self, **kwargs):
|
2020-01-15 15:40:30 -08:00
|
|
|
super.__init__(**kwargs)
|
2019-02-06 21:16:26 -08:00
|
|
|
self.init_background_lines()
|
|
|
|
|
|
|
|
def init_background_lines(self):
|
|
|
|
if self.faded_line_style is None:
|
2019-02-07 10:13:12 -08:00
|
|
|
style = dict(self.background_line_style)
|
|
|
|
# For anything numerical, like stroke_width
|
|
|
|
# and stroke_opacity, chop it in half
|
|
|
|
for key in style:
|
|
|
|
if isinstance(style[key], numbers.Number):
|
|
|
|
style[key] *= 0.5
|
|
|
|
self.faded_line_style = style
|
2019-02-06 21:16:26 -08:00
|
|
|
|
|
|
|
self.background_lines, self.faded_lines = self.get_lines()
|
|
|
|
self.background_lines.set_style(
|
|
|
|
**self.background_line_style,
|
|
|
|
)
|
|
|
|
self.faded_lines.set_style(
|
|
|
|
**self.faded_line_style,
|
|
|
|
)
|
|
|
|
self.add_to_back(
|
|
|
|
self.faded_lines,
|
|
|
|
self.background_lines,
|
2018-03-31 18:31:56 -07:00
|
|
|
)
|
|
|
|
|
2019-02-06 21:16:26 -08:00
|
|
|
def get_lines(self):
|
|
|
|
x_axis = self.get_x_axis()
|
|
|
|
y_axis = self.get_y_axis()
|
|
|
|
x_freq = self.x_line_frequency
|
|
|
|
y_freq = self.y_line_frequency
|
2018-03-31 18:31:56 -07:00
|
|
|
|
2019-02-06 21:16:26 -08:00
|
|
|
x_lines1, x_lines2 = self.get_lines_parallel_to_axis(
|
|
|
|
x_axis, y_axis, x_freq,
|
|
|
|
self.faded_line_ratio,
|
|
|
|
)
|
|
|
|
y_lines1, y_lines2 = self.get_lines_parallel_to_axis(
|
|
|
|
y_axis, x_axis, y_freq,
|
|
|
|
self.faded_line_ratio,
|
|
|
|
)
|
|
|
|
lines1 = VGroup(*x_lines1, *y_lines1)
|
|
|
|
lines2 = VGroup(*x_lines2, *y_lines2)
|
|
|
|
return lines1, lines2
|
|
|
|
|
|
|
|
def get_lines_parallel_to_axis(self, axis1, axis2, freq, ratio):
|
|
|
|
line = Line(axis1.get_start(), axis1.get_end())
|
|
|
|
dense_freq = (1 + ratio)
|
2019-03-23 10:51:47 -07:00
|
|
|
step = (1 / dense_freq) * freq
|
2019-02-06 21:16:26 -08:00
|
|
|
|
|
|
|
lines1 = VGroup()
|
|
|
|
lines2 = VGroup()
|
|
|
|
ranges = (
|
|
|
|
np.arange(0, axis2.x_max, step),
|
|
|
|
np.arange(0, axis2.x_min, -step),
|
|
|
|
)
|
|
|
|
for inputs in ranges:
|
|
|
|
for k, x in enumerate(inputs):
|
|
|
|
new_line = line.copy()
|
|
|
|
new_line.move_to(axis2.number_to_point(x))
|
|
|
|
if k % (1 + ratio) == 0:
|
|
|
|
lines1.add(new_line)
|
|
|
|
else:
|
|
|
|
lines2.add(new_line)
|
|
|
|
return lines1, lines2
|
2018-03-31 18:31:56 -07:00
|
|
|
|
2019-02-06 21:16:26 -08:00
|
|
|
def get_center_point(self):
|
|
|
|
return self.coords_to_point(0, 0)
|
2018-03-31 18:31:56 -07:00
|
|
|
|
|
|
|
def get_x_unit_size(self):
|
2019-02-06 21:16:26 -08:00
|
|
|
return self.get_x_axis().get_unit_size()
|
2018-03-31 18:31:56 -07:00
|
|
|
|
|
|
|
def get_y_unit_size(self):
|
2019-02-06 21:16:26 -08:00
|
|
|
return self.get_x_axis().get_unit_size()
|
2018-03-31 18:31:56 -07:00
|
|
|
|
|
|
|
def get_axes(self):
|
|
|
|
return self.axes
|
|
|
|
|
|
|
|
def get_vector(self, coords, **kwargs):
|
2019-02-06 21:16:26 -08:00
|
|
|
kwargs["buff"] = 0
|
|
|
|
return Arrow(
|
|
|
|
self.coords_to_point(0, 0),
|
|
|
|
self.coords_to_point(*coords),
|
|
|
|
**kwargs
|
|
|
|
)
|
2018-03-31 18:31:56 -07:00
|
|
|
|
2019-02-05 11:02:15 -08:00
|
|
|
def prepare_for_nonlinear_transform(self, num_inserted_curves=50):
|
2018-03-31 18:31:56 -07:00
|
|
|
for mob in self.family_members_with_points():
|
2019-02-05 11:02:15 -08:00
|
|
|
num_curves = mob.get_num_curves()
|
|
|
|
if num_inserted_curves > num_curves:
|
|
|
|
mob.insert_n_curves(
|
2019-02-06 21:16:26 -08:00
|
|
|
num_inserted_curves - num_curves
|
|
|
|
)
|
2018-03-31 18:31:56 -07:00
|
|
|
return self
|
|
|
|
|
2018-04-06 13:58:59 -07:00
|
|
|
|
2018-03-31 18:31:56 -07:00
|
|
|
class ComplexPlane(NumberPlane):
|
|
|
|
CONFIG = {
|
2018-04-06 13:58:59 -07:00
|
|
|
"color": BLUE,
|
|
|
|
"line_frequency": 1,
|
2018-03-31 18:31:56 -07:00
|
|
|
}
|
2018-04-06 13:58:59 -07:00
|
|
|
|
2018-03-31 18:31:56 -07:00
|
|
|
def number_to_point(self, number):
|
|
|
|
number = complex(number)
|
|
|
|
return self.coords_to_point(number.real, number.imag)
|
|
|
|
|
2019-06-23 16:25:22 -07:00
|
|
|
def n2p(self, number):
|
|
|
|
return self.number_to_point(number)
|
|
|
|
|
2018-03-31 18:31:56 -07:00
|
|
|
def point_to_number(self, point):
|
|
|
|
x, y = self.point_to_coords(point)
|
|
|
|
return complex(x, y)
|
|
|
|
|
2019-06-23 16:25:22 -07:00
|
|
|
def p2n(self, point):
|
|
|
|
return self.point_to_number(point)
|
|
|
|
|
2019-02-06 21:16:26 -08:00
|
|
|
def get_default_coordinate_values(self):
|
|
|
|
x_numbers = self.get_x_axis().default_numbers_to_display()
|
|
|
|
y_numbers = self.get_y_axis().default_numbers_to_display()
|
|
|
|
y_numbers = [
|
|
|
|
complex(0, y) for y in y_numbers if y != 0
|
|
|
|
]
|
|
|
|
return [*x_numbers, *y_numbers]
|
2018-03-31 18:31:56 -07:00
|
|
|
|
2019-02-06 21:16:26 -08:00
|
|
|
def get_coordinate_labels(self, *numbers, **kwargs):
|
2018-03-31 18:31:56 -07:00
|
|
|
if len(numbers) == 0:
|
2019-02-06 21:16:26 -08:00
|
|
|
numbers = self.get_default_coordinate_values()
|
|
|
|
|
|
|
|
self.coordinate_labels = VGroup()
|
2018-03-31 18:31:56 -07:00
|
|
|
for number in numbers:
|
2019-02-06 21:16:26 -08:00
|
|
|
z = complex(number)
|
|
|
|
if abs(z.imag) > abs(z.real):
|
|
|
|
axis = self.get_y_axis()
|
|
|
|
value = z.imag
|
2019-02-06 21:32:42 -08:00
|
|
|
kwargs = merge_dicts_recursively(
|
2019-02-06 21:16:26 -08:00
|
|
|
kwargs,
|
2019-02-06 21:32:42 -08:00
|
|
|
{"number_config": {"unit": "i"}},
|
|
|
|
)
|
2019-02-06 21:16:26 -08:00
|
|
|
else:
|
|
|
|
axis = self.get_x_axis()
|
|
|
|
value = z.real
|
|
|
|
number_mob = axis.get_number_mobject(value, **kwargs)
|
|
|
|
self.coordinate_labels.add(number_mob)
|
|
|
|
return self.coordinate_labels
|
2018-03-31 18:31:56 -07:00
|
|
|
|
|
|
|
def add_coordinates(self, *numbers):
|
2019-02-06 21:16:26 -08:00
|
|
|
self.add(self.get_coordinate_labels(*numbers))
|
2018-03-31 18:31:56 -07:00
|
|
|
return self
|