diff --git a/active_projects/fourier.py b/active_projects/fourier.py index f51029f9..395d834c 100644 --- a/active_projects/fourier.py +++ b/active_projects/fourier.py @@ -2455,18 +2455,57 @@ class WhiteComplexExponentialExpression(DrawFrequencyPlot): self.generate_center_of_mass_dot_update_anim() self.add(graph, pol_graph, wps_label) + self.set_variables_as_attrs(pol_graph, wps_label) + self.time_axes_group = VGroup(self.time_axes, graph) def show_winding_with_both_coordinates(self): - #TODO, tie dashed lines to dot + com_dot = self.center_of_mass_dot + plane = self.circle_plane + v_line = Line(ORIGIN, UP) + h_line = Line(ORIGIN, RIGHT) + lines = VGroup(v_line, h_line) + lines.highlight(PINK) + def lines_update(lines): + point = com_dot.get_center() + x, y = plane.point_to_coords(point) + h_line.put_start_and_end_on( + plane.coords_to_point(0, y), point + ) + v_line.put_start_and_end_on( + plane.coords_to_point(x, 0), point + ) + lines_update_anim = UpdateFromFunc(lines, lines_update) + lines_update_anim.update(0) + self.add(lines) self.change_frequency( - 2.0, run_time = 15, + 2.04, + added_anims = [ + lines_update_anim, + self.center_of_mass_dot_anim, + ], + run_time = 15, rate_func = bezier([0, 0, 1, 1]) ) self.wait() + self.dot_component_anim = lines_update_anim + def show_plane_as_complex_plane(self): - pass + to_fade = VGroup( + self.time_axes_group, self.pol_graph, self.wps_label + ) + plane = self.circle_plane + complex_plane_title = TextMobject("Complex plane") + complex_plane_title.add_background_rectangle() + complex_plane_title.to_edge(UP) + coordinate_labels = plane.get_coordinate_labels() + + self.play(FadeOut(to_fade)) + self.play(Write(complex_plane_title)) + self.play(Write(coordinate_labels)) + self.wait() + def show_eulers_formula(self): pass diff --git a/helpers.py b/helpers.py index 079b0b5e..85ad584e 100644 --- a/helpers.py +++ b/helpers.py @@ -252,14 +252,14 @@ def get_all_descendent_classes(Class): result.append(Child) return result -def filtered_locals(local_args): - result = local_args.copy() +def filtered_locals(caller_locals): + result = caller_locals.copy() ignored_local_args = ["self", "kwargs"] for arg in ignored_local_args: - result.pop(arg, local_args) + result.pop(arg, caller_locals) return result -def digest_config(obj, kwargs, local_args = {}): +def digest_config(obj, kwargs, caller_locals = {}): """ Sets init args and CONFIG values as local variables @@ -268,19 +268,25 @@ def digest_config(obj, kwargs, local_args = {}): be easily passed into instantiation, and is attached as an attribute of the object. """ - ### Assemble list of CONFIGs from all super classes + + # Assemble list of CONFIGs from all super classes classes_in_hierarchy = [obj.__class__] - configs = [] + static_configs = [] while len(classes_in_hierarchy) > 0: Class = classes_in_hierarchy.pop() classes_in_hierarchy += Class.__bases__ if hasattr(Class, "CONFIG"): - configs.append(Class.CONFIG) + static_configs.append(Class.CONFIG) #Order matters a lot here, first dicts have higher priority - all_dicts = [kwargs, filtered_locals(local_args), obj.__dict__] - all_dicts += configs + caller_locals = filtered_locals(caller_locals) + all_dicts = [kwargs, caller_locals, obj.__dict__] + all_dicts += static_configs + all_new_dicts = [kwargs, caller_locals] + static_configs obj.__dict__ = merge_config(all_dicts) + #Keep track of the configuration of objects upon + #instantiation + obj.initial_config = merge_config(all_new_dicts) def merge_config(all_dicts): all_config = reduce(op.add, [d.items() for d in all_dicts]) @@ -295,6 +301,15 @@ def merge_config(all_dicts): config[key] = merge_config([config[key], value]) return config +def soft_dict_update(d1, d2): + """ + Adds key values pairs of d2 to d1 only when d1 doesn't + already have that key + """ + for key, value in d2.items(): + if key not in d1: + d1[key] = value + def digest_locals(obj, keys = None): caller_locals = filtered_locals( inspect.currentframe().f_back.f_locals diff --git a/mobject/vectorized_mobject.py b/mobject/vectorized_mobject.py index ec1da178..21194a71 100644 --- a/mobject/vectorized_mobject.py +++ b/mobject/vectorized_mobject.py @@ -85,15 +85,17 @@ class VMobject(Mobject): return self def match_style(self, vmobject): - #TODO: Should this be smart about matching the - #style of the family members, if they happen to - #be different? self.set_style_data( stroke_color = vmobject.get_stroke_color(), stroke_width = vmobject.get_stroke_width(), fill_color = vmobject.get_fill_color(), fill_opacity = vmobject.get_fill_opacity(), + family = False ) + #TODO: This behaviro may not be optimal when submobject + #lists dont' have the same length + for sm1, sm2 in zip(self.submobjects, vmobject.submobjects): + sm1.match_style(sm2) return def fade(self, darkness = 0.5):