From aa236ea330320752b0ff2422baa36b3ff66a3e98 Mon Sep 17 00:00:00 2001 From: Grant Sanderson Date: Tue, 6 Oct 2015 15:27:40 -0700 Subject: [PATCH] Initial implementation of NumberPlane --- mobject/function_graphs.py | 124 ++++++++++++++++++++++++------------- 1 file changed, 82 insertions(+), 42 deletions(-) diff --git a/mobject/function_graphs.py b/mobject/function_graphs.py index ef84f086..264906d1 100644 --- a/mobject/function_graphs.py +++ b/mobject/function_graphs.py @@ -11,7 +11,7 @@ class FunctionGraph(Mobject1D): "color" : "lightblue", "x_min" : -10, "x_max" : 10, - "spacial_radius" : SPACE_WIDTH, + "spatial_radius" : SPACE_WIDTH, } def __init__(self, function, **kwargs): digest_config(self, FunctionGraph, kwargs, locals()) @@ -20,7 +20,7 @@ class FunctionGraph(Mobject1D): def generate_points(self): numerical_radius = (self.x_max - self.x_min)/2 numerical_center = (self.x_max + self.x_min)/2 - ratio = numerical_radius / self.spacial_radius + ratio = numerical_radius / self.spatial_radius epsilon = self.epsilon * ratio self.add_points([ np.array([(x-numerical_center)/ratio, self.function(x), 0]) @@ -58,43 +58,11 @@ class ParametricFunction(Mobject): for s in np.arange(-1, 1, self.epsilon) ]) -class Grid(Mobject1D): - DEFAULT_CONFIG = { - "color" : "green", - "radius" : max(SPACE_HEIGHT, SPACE_WIDTH), - "interval_size" : 1.0, - "subinterval_size" : 0.5, - } - def __init__(self, **kwargs): - digest_config(self, Grid, kwargs) - Mobject1D.__init__(self, **kwargs) - - def generate_points(self): - self.add_points([ - (sgns[0] * x, sgns[1] * y, 0) - for beta in np.arange(0, self.radius, self.interval_size) - for alpha in np.arange(0, self.radius, self.epsilon) - for sgns in it.product((-1, 1), (-1, 1)) - for x, y in [(alpha, beta), (beta, alpha)] - ]) - if self.subinterval_size: - si = self.subinterval_size - color = Color(self.color) - color.set_rgb([x/2 for x in color.get_rgb()]) - self.add_points([ - (sgns[0] * x, sgns[1] * y, 0) - for beta in np.arange(0, self.radius, si) - if abs(beta % self.interval_size) > self.epsilon - for alpha in np.arange(0, self.radius, self.epsilon) - for sgns in it.product((-1, 1), (-1, 1)) - for x, y in [(alpha, beta), (beta, alpha)] - ], color = color) - class NumberLine(Mobject1D): DEFAULT_CONFIG = { "color" : "skyblue", "numerical_radius" : SPACE_WIDTH, - "unit_length_to_spacial_width" : 1, + "unit_length_to_spatial_width" : 1, "tick_size" : 0.1, "tick_frequency" : 0.5, "leftmost_tick" : -int(SPACE_WIDTH), @@ -109,15 +77,15 @@ class NumberLine(Mobject1D): Mobject1D.__init__(self, **kwargs) def generate_points(self): - spacial_radius = self.numerical_radius*self.unit_length_to_spacial_width + spatial_radius = self.numerical_radius*self.unit_length_to_spatial_width self.add_points([ (b*x, 0, 0) - for x in np.arange(0, spacial_radius, self.epsilon) + for x in np.arange(0, spatial_radius, self.epsilon) for b in [-1, 1] ]) self.index_of_left = np.argmin(self.points[:,0]) self.index_of_right = np.argmax(self.points[:,0]) - spacial_tick_frequency = self.tick_frequency*self.unit_length_to_spacial_width + spatial_tick_frequency = self.tick_frequency*self.unit_length_to_spatial_width self.add_points([ (x, y, 0) for num in self.get_tick_numbers() @@ -151,7 +119,7 @@ class NumberLine(Mobject1D): ) def point_to_number(self, point): - return self.number_at_center + point[0]/self.unit_length_to_spacial_width + return self.number_at_center + point[0]/self.unit_length_to_spatial_width def default_numbers_to_display(self): return self.get_tick_numbers()[::2] @@ -175,7 +143,7 @@ class NumberLine(Mobject1D): num_string = str(number)[:num_decimal_places] mob = tex_mobject(num_string) vert_scale = 2*self.tick_size/mob.get_height() - hori_scale = self.tick_frequency*self.unit_length_to_spacial_width/mob.get_width() + hori_scale = self.tick_frequency*self.unit_length_to_spatial_width/mob.get_width() mob.scale(min(vert_scale, hori_scale)) mob.shift(self.number_to_point(number)) mob.shift(self.get_vertical_number_offset()) @@ -192,7 +160,7 @@ class NumberLine(Mobject1D): class UnitInterval(NumberLine): DEFAULT_CONFIG = { "numerical_radius" : 0.5, - "unit_length_to_spacial_width" : 2*(SPACE_WIDTH-1), + "unit_length_to_spatial_width" : 2*(SPACE_WIDTH-1), "tick_frequency" : 0.1, "leftmost_tick" : 0, "number_at_center" : 0.5, @@ -210,7 +178,79 @@ class Axes(CompoundMobject): CompoundMobject.__init__(self, x_axis, y_axis) - +class NumberPlane(Mobject1D): + DEFAULT_CONFIG = { + "color" : "skyblue", + "x_radius" : SPACE_WIDTH, + "y_radius" : SPACE_HEIGHT, + "x_unit_to_spatial_width" : 1, + "y_uint_to_spatial_height" : 1, + "x_line_frequency" : 1, + "x_faded_line_frequency" : 0.5, + "y_line_frequency" : 1, + "y_faded_line_frequency" : 0.5, + "fade_factor" : 0.3, + "number_scale_factor" : 0.25, + "num_pair_at_center" : np.array((0, 0)), + } + def __init__(self, **kwargs): + digest_config(self, NumberPlane, kwargs) + Mobject1D.__init__(self, **kwargs) + + def generate_points(self): + color = self.color + faded = Color(rgb = self.fade_factor*np.array(color.get_rgb())) + colors = iter([faded, color]) + for freq in self.x_faded_line_frequency, self.x_line_frequency: + self.add_points([ + (sgns[0]*self.x_unit_to_spatial_width*x, sgns[1]*y, 0) + for x in np.arange(0, self.x_radius, freq) + for y in np.arange(0, self.y_radius, self.epsilon) + for sgns in it.product([-1, 1], [-1, 1]) + ], color = colors.next()) + #Horizontal lines + colors = iter([faded, color]) + for freq in self.y_faded_line_frequency, self.y_line_frequency: + self.add_points([ + (sgns[0]*x, sgns[1]*self.y_uint_to_spatial_height*y, 0) + for x in np.arange(0, self.x_radius, self.epsilon) + for y in np.arange(0, self.y_radius, freq) + for sgns in it.product([-1, 1], [-1, 1]) + ], color = colors.next()) + self.shift(self.get_center_point()) + + def get_center_point(self): + return self.num_pair_to_point(self.num_pair_at_center) + + def num_pair_to_point(self, pair): + pair = pair + self.num_pair_at_center + return pair[0]*self.x_unit_to_spatial_width*RIGHT + \ + pair[1]*self.y_uint_to_spatial_height*UP + + def get_coordinate_labels(self, x_vals = None, y_vals = None): + result = [] + nudge = 0.1*(DOWN+RIGHT) + if x_vals == None and y_vals == None: + x_vals = range(-int(self.x_radius), int(self.x_radius)) + y_vals = range(-int(self.y_radius), int(self.y_radius)) + for index, vals in zip([0, 1], [x_vals, y_vals]): + num_pair = [0, 0] + for val in vals: + num_pair[index] = val + point = self.num_pair_to_point(num_pair) + num = tex_mobject(str(val)) + num.scale(self.number_scale_factor) + num.shift(point-num.get_corner(UP+LEFT)+nudge) + result.append(num) + return result + + def add_coordinates(self, x_vals = None, y_vals = None): + self.add(*self.get_coordinate_labels(x_vals, y_vals)) + return self + +class ComplexPlane(NumberPlane): + #TODO + pass