diff --git a/old_projects/WindingNumber.py b/active_projects/WindingNumber.py similarity index 92% rename from old_projects/WindingNumber.py rename to active_projects/WindingNumber.py index c2d20fef..2601201a 100644 --- a/old_projects/WindingNumber.py +++ b/active_projects/WindingNumber.py @@ -1,7 +1,5 @@ from big_ol_pile_of_manim_imports import * -import time - import mpmath mpmath.mp.dps = 7 @@ -409,9 +407,7 @@ def resit_near(x, m): # TODO?: Perhaps use modulus of (uniform) continuity instead of num_checkpoints, calculating # latter as needed from former? -# -# "cheap" argument only used for diagnostic testing right now -def make_alpha_winder(func, start, end, num_checkpoints, cheap = False): +def make_alpha_winder(func, start, end, num_checkpoints): check_points = [None for i in range(num_checkpoints)] check_points[0] = func(start) step_size = fdiv(end - start, num_checkpoints) @@ -421,15 +417,9 @@ def make_alpha_winder(func, start, end, num_checkpoints, cheap = False): func(start + (i + 1) * step_size), check_points[i]) def return_func(alpha): - if cheap: - return alpha # A test to see if this func is responsible for slowdown - index = clamp(0, num_checkpoints - 1, int(alpha * num_checkpoints)) x = interpolate(start, end, alpha) - if cheap: - return check_points[index] # A more principled test that at least returns a reasonable answer - else: - return resit_near(func(x), check_points[index]) + return resit_near(func(x), check_points[index]) return return_func # The various inconsistent choices of what datatype to use where are a bit of a mess, @@ -566,7 +556,6 @@ def walker_animation_with_display( show_arrows = True, scale_arrows = False, num_decimal_points = 1, - include_background_rectangle = True, **kwargs ): @@ -582,15 +571,13 @@ def walker_animation_with_display( if number_update_func != None: display = DecimalNumber(0, num_decimal_points = num_decimal_points, - fill_color = WHITE if include_background_rectangle else BLACK, - include_background_rectangle = include_background_rectangle) - if include_background_rectangle: - display.background_rectangle.fill_opacity = 0.5 - display.background_rectangle.fill_color = GREY - display.background_rectangle.scale(1.2) + fill_color = WHITE, + include_background_rectangle = True) + display.background_rectangle.fill_opacity = 0.5 + display.background_rectangle.fill_color = GREY + display.background_rectangle.scale(1.2) displaycement = 0.5 * DOWN # How about that pun, eh? - # display.move_to(walker.get_center() + displaycement) - display.next_to(walker, DOWN+RIGHT, SMALL_BUFF) + display.move_to(walker.get_center() + displaycement) display_anim = ChangingDecimal(display, number_update_func, tracked_mobject = walker_anim.compound_walker.walker, @@ -608,7 +595,6 @@ def LinearWalker( number_update_func = None, show_arrows = True, scale_arrows = False, - include_background_rectangle = True, **kwargs ): walk_func = lambda alpha : interpolate(start_coords, end_coords, alpha) @@ -619,7 +605,6 @@ def LinearWalker( number_update_func = number_update_func, show_arrows = show_arrows, scale_arrows = scale_arrows, - include_background_rectangle = include_background_rectangle, **kwargs) class ColorMappedByFuncScene(Scene): @@ -732,8 +717,7 @@ class PiWalker(ColorMappedByFuncScene): "show_num_plane" : False, "draw_lines" : True, "num_checkpoints" : 10, - "num_decimal_points" : 1, - "include_background_rectangle" : False, + "num_decimal_points" : 1 } def construct(self): @@ -789,7 +773,6 @@ class PiWalker(ColorMappedByFuncScene): run_time = self.step_run_time, walker_stroke_color = WALKER_LIGHT_COLOR if self.color_foreground_not_background else BLACK, num_decimal_points = self.num_decimal_points, - include_background_rectangle = self.include_background_rectangle, ) if self.display_odometer: @@ -971,18 +954,6 @@ class EquationSolver2dNode(object): bfs_nodes = self.hacky_bfs() return Succession(*map(lambda n : n.first_anim, bfs_nodes)) - def play_in_bfs(self, scene, border_anim): - bfs_nodes = self.hacky_bfs() - print "Number of nodes: ", len(bfs_nodes) - - if len(bfs_nodes) < 1: - print "Less than 1 node! Aborting!" - return - - scene.play(bfs_nodes[0].first_anim, border_anim) - for node in bfs_nodes[1:]: - scene.play(node.first_anim) - class EquationSolver2d(ColorMappedObjectsScene): CONFIG = { "camera_config" : {"use_z_coordinate_for_display_order": True}, @@ -990,7 +961,7 @@ class EquationSolver2d(ColorMappedObjectsScene): "initial_upper_x" : 5, "initial_lower_y" : -3, "initial_upper_y" : 3, - "num_iterations" : 0, + "num_iterations" : 1, "num_checkpoints" : 10, # Should really merge this into one enum-style variable @@ -998,9 +969,6 @@ class EquationSolver2d(ColorMappedObjectsScene): "display_in_bfs" : False, "use_fancy_lines" : True, - "line_color" : WHITE, # Only used for non-fancy lines - - # TODO: Consider adding a "find_all_roots" flag, which could be turned off # to only explore one of the two candidate subrectangles when both are viable @@ -1018,26 +986,18 @@ class EquationSolver2d(ColorMappedObjectsScene): # Used for UhOhScene; "manual_wind_override" : None, - "show_cursor" : True, + "show_cursor" : False, - "linger_parameter" : 0.5, - - "use_separate_plays" : False, - - "use_cheap_winding_numbers" : False, # To use this, make num_checkpoints large + "linger_parameter" : 0.2, } def construct(self): - if self.num_iterations == 0: - print "You forgot to set num_iterations (maybe you meant to subclass something other than EquationSolver2d directly?)" - return - ColorMappedObjectsScene.construct(self) num_plane = self.num_plane clockwise_val_func = lambda p : -point_to_rev(self.func(p)) - base_line = Line(UP, RIGHT, stroke_width = border_stroke_width, color = self.line_color) + base_line = Line(UP, RIGHT, stroke_width = border_stroke_width, color = WHITE) if self.use_fancy_lines: base_line.color_using_background_image(self.background_image_file) @@ -1077,7 +1037,7 @@ class EquationSolver2d(ColorMappedObjectsScene): return EquationSolver2dNode(empty_animation) def draw_line_return_wind(start, end, start_wind, should_linger = False, draw_line = True): - alpha_winder = make_alpha_winder(clockwise_val_func, start, end, self.num_checkpoints, cheap = self.use_cheap_winding_numbers) + alpha_winder = make_alpha_winder(clockwise_val_func, start, end, self.num_checkpoints) a0 = alpha_winder(0) rebased_winder = lambda alpha: alpha_winder(alpha) - a0 + start_wind colored_line = Line(num_plane.coords_to_point(*start) + IN, num_plane.coords_to_point(*end) + IN) @@ -1132,7 +1092,7 @@ class EquationSolver2d(ColorMappedObjectsScene): width = rect.get_width() height = rect.get_height() - cursor.move_to(num_plane.coords_to_point(center_x, center_y) + 10 * IN) + cursor.move_to(num_plane.coords_to_point(center_x, center_y)) cursor.scale(min(width, height)) # Do a quick FadeIn, wait, and quick FadeOut on the cursor, matching rectangle-drawing time @@ -1144,11 +1104,7 @@ class EquationSolver2d(ColorMappedObjectsScene): anim = AnimationGroup(anim, cursor_anim) - override_wind = head(manual_wind_override) - if override_wind != None: - total_wind = override_wind - else: - total_wind = round(wind_so_far) + total_wind = head(manual_wind_override) or round(wind_so_far) if total_wind == 0: coords = [ @@ -1241,17 +1197,15 @@ class EquationSolver2d(ColorMappedObjectsScene): rate_func = rect_rate ) - print "About to do the big Play; for reference, the current time is ", time.strftime("%H:%M:%S") - - if self.use_separate_plays: - node.play_in_bfs(self, border_anim) - else: - self.play(anim, border_anim) - - print "All done; for reference, the current time is ", time.strftime("%H:%M:%S") + self.play(anim, border_anim) self.wait() + # In case we wish to reference these later, as had been done in the + # WindingNumber_G/SearchSpacePerimeterVsArea scene at one point + self.node = node + self.anim = anim + # TODO: Perhaps have option for bullets (pulses) to fade out and in at ends of line, instead of # jarringly popping out and in? # @@ -1264,7 +1218,7 @@ class LinePulser(ContinualAnimation): self.pulse_time = pulse_time self.bullets = [bullet_template.copy() for i in range(num_bullets)] self.output_func = output_func - ContinualAnimation.__init__(self, VGroup(*self.bullets), **kwargs) + ContinualAnimation.__init__(self, VGroup(line, VGroup(*self.bullets)), **kwargs) def update_mobject(self, dt): alpha = self.external_time % self.pulse_time @@ -1999,9 +1953,7 @@ class LoopSplitScene(ColorMappedObjectsScene): def flash_circles(circles): self.play(LaggedStart(FadeIn, VGroup(circles))) - self.wait() - self.play(FadeOut(VGroup(circles))) - self.wait() + self.play(*map(FadeOut, circles)) self.add(left_square_lines_vmobject, right_square_lines_vmobject) self.remove(*midline_lines) @@ -2015,17 +1967,15 @@ class LoopSplitScene(ColorMappedObjectsScene): self.wait() flash_circles([indicate_circle(l) for l in left_square_lines]) self.play(line_fade(faded, 1, right_square_lines_vmobject), *bullet_list_fade(1, 0, left_square_bullets)) - self.wait() self.add(*right_square_anims) self.play(line_fade(1, faded, left_square_lines_vmobject), *bullet_list_fade(0, 1, right_square_bullets)) self.wait() flash_circles([indicate_circle(l) for l in right_square_lines]) self.play(line_fade(faded, 1, left_square_lines_vmobject), *bullet_list_fade(1, 0, right_square_bullets)) - self.wait() - self.play(*bullet_list_fade(0, 1, left_square_bullets + right_square_bullets)) self.wait() + self.play(*bullet_list_fade(0, 1, left_square_bullets + right_square_bullets)) outside_circlers = [ indicate_circle(left_line), @@ -2037,15 +1987,20 @@ class LoopSplitScene(ColorMappedObjectsScene): inner_circle = indicate_circle(midline_lines[0]) self.play(FadeIn(inner_circle)) - self.wait() self.play(FadeOut(inner_circle), line_fade(1, 0, midline_lines_vmobject), *bullet_list_fade(1, 0, midline_bullets)) - self.wait() - - # Repeat for effect, goes well with narration - self.play(FadeIn(inner_circle), line_fade(0, 1, midline_lines_vmobject), *bullet_list_fade(0, 1, midline_bullets)) - self.wait() - self.play(FadeOut(inner_circle), line_fade(1, 0, midline_lines_vmobject), *bullet_list_fade(1, 0, midline_bullets)) - self.wait() + + self.wait(3) + +# Is there a way to abstract this into a general process to derive a new mapped scene from an old scene? +class LoopSplitSceneMapped(LoopSplitScene): + + def setup(self): + left_camera = Camera(**self.camera_config) + right_camera = MappingCamera( + mapping_func = lambda (x, y, z) : complex_to_R3(((complex(x,y) + 3)**1.1) - 3), + **self.camera_config) + split_screen_camera = SplitScreenCamera(left_camera, right_camera, **self.camera_config) + self.camera = split_screen_camera # TODO: Perhaps do extra illustration of zooming out and winding around a large circle, # to illustrate relation between degree and large-scale winding number @@ -2053,121 +2008,16 @@ class FundThmAlg(EquationSolver2d): CONFIG = { "func" : plane_func_by_wind_spec((1, 2), (-1, 1.5), (-1, 1.5)), "num_iterations" : 2, + "use_fancy_lines" : True, } class SolveX5MinusXMinus1(EquationSolver2d): - CONFIG = { - "func" : plane_func_from_complex_func(lambda c : c**5 - c - 1), - "num_iterations" : 10, - "show_cursor" : True, - "display_in_bfs" : True, - } - -class PureColorMapOfX5Thing(PureColorMap): - CONFIG = { - "func" : plane_func_from_complex_func(lambda c : c**5 - c - 1), - } - -class X5ThingWithRightHalfGreyed(SolveX5MinusXMinus1): - CONFIG = { - "num_iterations" : 3, - "manual_wind_override" : (1, None, (1, (0, None, None), (0, None, None))) - } - -class SolveX5MinusXMinus1_5Iterations(EquationSolver2d): CONFIG = { "func" : plane_func_from_complex_func(lambda c : c**5 - c - 1), "num_iterations" : 5, - "show_cursor" : True, - "display_in_bfs" : True, - "manual_wind_override" : (None, None, (None, (0, None, None), (0, None, None))) + "use_fancy_lines" : True, } -class X5_Monster_Red_Lines(SolveX5MinusXMinus1_5Iterations): - CONFIG = { - "use_separate_plays" : True, - "use_fancy_lines" : False, - "line_color" : RED, - } - -class X5_Monster_Green_Lines(X5_Monster_Red_Lines): - CONFIG = { - "line_color" : GREEN, - } - -class X5_Monster_Red_Lines_Long(X5_Monster_Red_Lines): - CONFIG = { - "num_iterations" : 6 - } - -class X5_Monster_Green_Lines_Long(X5_Monster_Green_Lines): - CONFIG = { - "num_iterations" : 6 - } - -class X5_Monster_Red_Lines_Little_More(X5_Monster_Red_Lines_Long): - CONFIG = { - "num_iterations" : 7 - } - -class X5_Monster_Green_Lines_Little_More(X5_Monster_Green_Lines_Long): - CONFIG = { - "num_iterations" : 7 - } - -class X5_Monster_Red_Lines_No_Numbers(X5_Monster_Red_Lines): - CONFIG = { - "num_iterations" : 3, - "show_winding_numbers" : False, - } - -class X5_Monster_Green_Lines_No_Numbers(X5_Monster_Green_Lines): - CONFIG = { - "num_iterations" : 3, - "show_winding_numbers" : False, - } - -class SolveX5MinusXMinus1_3Iterations(EquationSolver2d): - CONFIG = { - "func" : plane_func_from_complex_func(lambda c : c**5 - c - 1), - "num_iterations" : 3, - "show_cursor" : True, - "display_in_bfs" : True, - } - -class Diagnostic(SolveX5MinusXMinus1_3Iterations): - CONFIG = { - # I think the combination of these two makes things slow - "use_separate_plays" : not False, # This one isn't important to set any particular way, so let's leave it like this - "use_fancy_lines" : True, - - # This causes a small slowdown (before rendering, in particular), but not the big one, I think - "show_winding_numbers" : True, - - # This doesn't significantly matter for rendering time, I think - "camera_config" : {"use_z_coordinate_for_display_order" : True} - } - -# All above flags False (meaning not db = False): just under 30 it/s -# not db = True: 30 -# use_fancy_lines = True: 30 at first (if scene.play(bfs_nodes[0].first_anim, border_anim is off), but then drops to 3 (or drops right away if that simultaneous play is on) -# use_z_coordinate = True: 30 -# show_winding_numbers = True: 10 -# winding AND use_fancy_lines: 10 -# not db AND fancy_lines AND z_coords = true, winding = false: 3. Not 30, but 3. Slow. -# db AND use_fancy: 3. Slow. -# fancy AND z_coords: 30. Fast. [Hm, this may have been a mistake; fancy and z_coords is now slow?] -# fancy, winding, AND z_coords, but not (not db): 10 -# not db, winding, AND z_coords, but not fancy: 10 - -# class DiagnosticB(Diagnostic): -# CONFIG = { -# "num_iterations" : 3, -# #"num_checkpoints" : 100, -# #"show_winding_numbers" : False, -# #"use_cheap_winding_numbers" : True, -# } - class SolveX5MinusXMinus1Parallel(SolveX5MinusXMinus1): CONFIG = { "display_in_parallel" : True @@ -2186,37 +2036,6 @@ class PreviewClip(EquationSolver2d): "use_fancy_lines" : True, } -class ParallelClip(EquationSolver2d): - CONFIG = { - "func" : plane_func_by_wind_spec( - (-3, -1.3, 2), (0.1, 0.2, 1), (2.8, -2, 1) - ), - "num_iterations" : 5, - "display_in_parallel" : True, - } - -class EquationSolver2dMatchBreakdown(EquationSolver2d): - CONFIG = { - "func" : plane_func_by_wind_spec( - (-2, 0.3, 2), (2, -0.2, 1) # Not an exact match, because our breakdown function has a zero along midlines... - ), - "num_iterations" : 5, - "display_in_parallel" : True, - "show_cursor" : True - } - -class EquationSolver2dMatchBreakdown_parallel(EquationSolver2dMatchBreakdown): - CONFIG = { - "display_in_parallel" : True, - "display_in_bfs" : False, - } - -class EquationSolver2dMatchBreakdown_bfs(EquationSolver2dMatchBreakdown): - CONFIG = { - "display_in_parallel" : False, - "display_in_bfs" : True, - } - class QuickPreview(PreviewClip): CONFIG = { "num_iterations" : 3, @@ -2234,11 +2053,6 @@ class LongEquationSolver(EquationSolver2d): "show_cursor" : True, } -class QuickPreviewUnfancy(LongEquationSolver): - CONFIG = { - # "use_fancy_lines" : False, - } - # TODO: Borsuk-Ulam visuals # Note: May want to do an ordinary square scene, then MappingCamera it into a circle # class BorsukUlamScene(PiWalker): @@ -2665,6 +2479,18 @@ class ShowBack(PiWalkerRect): "func" : plane_func_by_wind_spec((1, 2), (-1, 1.5), (-1, 1.5)) } +class Diagnostic(Scene): + def construct(self): + testList = map(lambda n : (n, rev_to_rgba(n)), [0, 0.1, 0.2, 0.3, 0.4]) + print "Here you go:", testList + self.wait() + +class DiagnosticColorMap(PureColorMap): + CONFIG = { + "func" : lambda (x, y) : (25 * x, 25 * y), + "show_num_plane" : False, + } + class PiWalkerOdometerTest(PiWalkerExamplePlaneFunc): CONFIG = { "display_odometer" : True diff --git a/old_projects/WindingNumber_G.py b/active_projects/WindingNumber_G.py similarity index 97% rename from old_projects/WindingNumber_G.py rename to active_projects/WindingNumber_G.py index 501fc289..fa6a8354 100644 --- a/old_projects/WindingNumber_G.py +++ b/active_projects/WindingNumber_G.py @@ -1896,20 +1896,6 @@ class TinyLoopAroundRed(TinyLoop): "target_coords" : (-1, 1), } -class ConfusedPiCreature(PiCreatureScene): - def construct(self): - morty = self.pi_creature - morty.set_color(YELLOW_E) - morty.flip() - morty.center() - - self.play(morty.change, "awe", DOWN+3*RIGHT) - self.wait(2) - self.play(morty.change, "confused") - self.wait(2) - self.play(morty.change, "pondering") - self.wait(2) - class FailureOfComposition(ColorMappedObjectsScene): CONFIG = { "func" : lambda p : ( @@ -2162,11 +2148,7 @@ class TransitionFromPathsToBoundaries(ColorMappedObjectsScene): CONFIG = { "func" : plane_func_by_wind_spec( (-2, 0, 2), (2, 0, 1) - ), - "dot_fill_opacity" : 1, - "dot_stroke_width" : 1, - "include_walkers" : True, - "include_question_mark" : True, + ) } def construct(self): ColorMappedObjectsScene.construct(self) @@ -2196,10 +2178,7 @@ class TransitionFromPathsToBoundaries(ColorMappedObjectsScene): #Setup region labels - sum_tex = "x+y" - if self.include_question_mark: - sum_tex += "\\, ?" - for square, tex in (left_square, "x"), (right_square, "y"), (joint_rect, sum_tex): + for square, tex in (left_square, "x"), (right_square, "y"), (joint_rect, "x+y \\, ?"): square.label = TextMobject("Winding = ", "$%s$"%tex) square.label.move_to(square) @@ -2253,7 +2232,7 @@ class TransitionFromPathsToBoundaries(ColorMappedObjectsScene): path_arc = TAU/6 ), FadeIn(joint_rect.label[1][1]), - FadeIn(joint_rect.label[1][3:]), + FadeIn(joint_rect.label[1][3]), FadeOut(right_square.label[0]), Transform( right_square.label[1], joint_rect.label[1][2], @@ -2302,12 +2281,9 @@ class TransitionFromPathsToBoundaries(ColorMappedObjectsScene): #Setup dot, arrow and label dot = self.dot = Dot(radius = 0.1) - dot.set_stroke(WHITE, self.dot_stroke_width) + dot.set_stroke(WHITE, 1) update_dot_color = ContinualUpdateFromFunc( - dot, lambda d : d.set_fill( - get_output_color(), - self.dot_fill_opacity - ) + dot, lambda d : d.set_fill(get_output_color()) ) label = DecimalNumber(0, num_decimal_points = 1) @@ -2318,7 +2294,7 @@ class TransitionFromPathsToBoundaries(ColorMappedObjectsScene): arrow_length = 0.75 arrow = Vector(arrow_length*RIGHT) - arrow.set_stroke(WHITE, self.dot_stroke_width) + arrow.set_stroke(WHITE, 1) def arrow_update_func(arrow): arrow.set_fill(get_output_color(), 1) arrow.rotate(-TAU*get_output_rev() - arrow.get_angle()) @@ -2327,8 +2303,7 @@ class TransitionFromPathsToBoundaries(ColorMappedObjectsScene): return arrow update_arrow = ContinualUpdateFromFunc(arrow, arrow_update_func) - if self.include_walkers: - self.add(update_arrow, update_dot_color, label_upadte) + self.add(update_arrow, update_dot_color, label_upadte) return dot def position_dot(self, point): @@ -2336,17 +2311,6 @@ class TransitionFromPathsToBoundaries(ColorMappedObjectsScene): self.start_rev = self.get_output_rev() self.curr_winding = 0 -class TransitionFromPathsToBoundariesArrowless(TransitionFromPathsToBoundaries): - CONFIG = { - "func" : plane_func_by_wind_spec( - (-2, 0, 2), (2, 0, 1) - ), - "dot_fill_opacity" : 0, - "dot_stroke_width" : 0, - "include_walkers" : False, - "include_question_mark" : False, - } - class BreakDownLoopWithNonzeroWinding(TransitionFromPathsToBoundaries): def construct(self): zero_point = 2*LEFT @@ -2625,7 +2589,9 @@ class PolynomialTerms(MonomialTerm): class SearchSpacePerimeterVsArea(EquationSolver2d): CONFIG = { - "func" : example_plane_func, + "func" : plane_func_by_wind_spec( + (-3, -1.3, 2), (0.1, 0.2, 1), (2.8, -2, 1) + ), "num_iterations" : 15, "display_in_parallel" : False, "use_fancy_lines" : True, @@ -2688,6 +2654,7 @@ class SearchSpacePerimeterVsArea(EquationSolver2d): self.play(FadeOut(full_rect)) self.wait() +<<<<<<< HEAD:old_projects/WindingNumber_G.py class ShowPolynomialFinalState(SolveX5MinusXMinus1): CONFIG = { "num_iterations" : 15, @@ -2905,6 +2872,8 @@ class AllOfTheVideos(Scene): self.play(LaggedStart(FadeIn, images, run_time = 4)) self.wait() +======= +>>>>>>> parent of feeb9ec... Merge branch 'master' into eop:active_projects/WindingNumber_G.py class EndingCredits(Scene): def construct(self): text = TextMobject( @@ -3218,33 +3187,8 @@ class EndScreen(PatreonEndScreen, PiCreatureScene): self.play(morty.change, mode) self.wait(2) -class Thumbnail(SearchSpacePerimeterVsArea): - CONFIG = { - "num_iterations" : 18, - "func" : plane_func_by_wind_spec( - (-3, -1.3, 2), (0.1, 0.2, 1), (2.8, -2, 1) - ), - } - def construct(self): - self.force_skipping() - EquationSolver2d.construct(self) - self.revert_to_original_skipping_status() - - mobjects = VGroup(*self.get_mobjects()) - lines = VGroup() - rects = VGroup() - get_length = lambda mob : max(mob.get_width(), mob.get_height()) - for mob in mobjects: - if mob.background_image_file is not None: - mob.set_stroke(width = 4*np.sqrt(get_length(mob))) - lines.add(mob) - elif isinstance(mob, Polygon): - rects.add(mob) - else: - self.remove(mob) - - self.clear() - self.add(lines) + + diff --git a/once_useful_constructs/complex_transformation_scene.py b/once_useful_constructs/complex_transformation_scene.py index efbbe21b..7d008b3a 100644 --- a/once_useful_constructs/complex_transformation_scene.py +++ b/once_useful_constructs/complex_transformation_scene.py @@ -156,6 +156,112 @@ class ComplexTransformationScene(Scene): *added_anims ) +<<<<<<< HEAD:once_useful_constructs/complex_transformation_scene.py +======= +##### Unsure about what comes under here... + +def complex_string(complex_num): + return filter(lambda c : c not in "()", str(complex_num)) + +class ComplexPlane(NumberPlane): + CONFIG = { + "color" : BLUE, + "unit_size" : 1, + "line_frequency" : 1, + "faded_line_frequency" : 0.5, + } + def __init__(self, **kwargs): + digest_config(self, kwargs) + kwargs.update({ + "x_unit_size" : self.unit_size, + "y_unit_size" : self.unit_size, + "x_line_frequency" : self.line_frequency, + "x_faded_line_frequency" : self.faded_line_frequency, + "y_line_frequency" : self.line_frequency, + "y_faded_line_frequency" : self.faded_line_frequency, + }) + NumberPlane.__init__(self, **kwargs) + + def number_to_point(self, number): + number = complex(number) + return self.coords_to_point(number.real, number.imag) + + def point_to_number(self, point): + x, y = self.point_to_coords(point) + return complex(x, y) + + def get_coordinate_labels(self, *numbers): + # TODO: Should merge this with the code from NumberPlane.get_coordinate_labels + + result = VGroup() + nudge = 0.1*(DOWN+RIGHT) + if len(numbers) == 0: + numbers = range(-int(self.x_radius), int(self.x_radius)+1) + numbers += [ + complex(0, y) + for y in range(-int(self.y_radius), int(self.y_radius)+1) + ] + for number in numbers: + if number == complex(0, 0): + continue + point = self.number_to_point(number) + num_str = str(number).replace("j", "i") + if num_str.startswith("0"): + num_str = "0" + elif num_str in ["1i", "-1i"]: + num_str = num_str.replace("1", "") + num_mob = TexMobject(num_str) + num_mob.add_background_rectangle() + num_mob.scale_to_fit_height(self.written_coordinate_height) + num_mob.next_to(point, DOWN+LEFT, SMALL_BUFF) + result.add(num_mob) + return result + + def add_coordinates(self, *numbers): + self.add(*self.get_coordinate_labels(*numbers)) + return self + + def add_spider_web(self, circle_freq = 1, angle_freq = np.pi/6): + # This code no longer works because it has this reference to self.fade_factor + # which is never initialized. Shall we delete this little-used function entirely? + self.fade(self.fade_factor) + config = { + "color" : self.color, + "density" : self.density, + } + for radius in np.arange(circle_freq, SPACE_WIDTH, circle_freq): + self.add(Circle(radius = radius, **config)) + for angle in np.arange(0, 2*np.pi, angle_freq): + end_point = np.cos(angle)*RIGHT + np.sin(angle)*UP + end_point *= SPACE_WIDTH + self.add(Line(ORIGIN, end_point, **config)) + return self + +class ComplexFunction(ApplyPointwiseFunction): + def __init__(self, function, mobject = ComplexPlane, **kwargs): + if "path_func" not in kwargs: + self.path_func = path_along_arc( + np.log(function(complex(1))).imag + ) + ApplyPointwiseFunction.__init__( + self, + lambda (x, y, z) : complex_to_R3(function(complex(x, y))), + instantiate(mobject), + **kwargs + ) + +class ComplexHomotopy(Homotopy): + def __init__(self, complex_homotopy, mobject = ComplexPlane, **kwargs): + """ + Complex Hootopy a function Cx[0, 1] to C + """ + def homotopy(event): + x, y, z, t = event + c = complex_homotopy((complex(x, y), t)) + return (c.real, c.imag, z) + Homotopy.__init__(self, homotopy, mobject, *args, **kwargs) + +>>>>>>> parent of feeb9ec... Merge branch 'master' into eop:topics/complex_numbers.py