def get_time_progression( self, run_time: float, n_iterations: int | None = None, desc: str = "", override_skip_animations: bool = False ) -> list[float] | np.ndarray | ProgressDisplay: if self.skip_animations and not override_skip_animations: return [run_time] times = np.arange(0, run_time, 1 / self.camera.fps) if self.file_writer.has_progress_display: self.file_writer.set_progress_display_subdescription(desc) if self.show_animation_progress: return ProgressDisplay( times, total=n_iterations, leave=self.leave_progress_bars, ascii=True if platform.system() == 'Windows' else None, desc=desc, ) else: return times
def get_time_progression(self, run_time): if self.skip_animations: times = [run_time] else: step = self.frame_duration times = np.arange(0, run_time, step) time_progression = ProgressDisplay(times) return time_progression
def get_time_progression(self, animations): run_time = animations[0].run_time times = np.arange(0, run_time, self.frame_duration) time_progression = ProgressDisplay(times) time_progression.set_description("".join([ "Animation %d: " % self.num_plays, str(animations[0]), (", etc." if len(animations) > 1 else ""), ])) return time_progression
def open_movie_pipe(self, file_path: str) -> None: stem, ext = os.path.splitext(file_path) self.final_file_path = file_path self.temp_file_path = stem + "_temp" + ext fps = self.scene.camera.frame_rate width, height = self.scene.camera.get_pixel_shape() command = [ FFMPEG_BIN, '-y', # overwrite output file if it exists '-f', 'rawvideo', '-s', f'{width}x{height}', # size of one frame '-pix_fmt', 'rgba', '-r', str(fps), # frames per second '-i', '-', # The input comes from a pipe '-vf', 'vflip', '-an', # Tells FFMPEG not to expect any audio '-loglevel', 'error', ] if self.movie_file_extension == ".mov": # This is if the background of the exported # video should be transparent. command += [ '-vcodec', 'prores_ks', ] elif self.movie_file_extension == ".gif": command += [] else: command += [ '-vcodec', 'libx264', '-pix_fmt', 'yuv420p', ] command += [self.temp_file_path] self.writing_process = sp.Popen(command, stdin=sp.PIPE) if self.total_frames > 0: self.progress_display = ProgressDisplay( range(self.total_frames), # bar_format="{l_bar}{bar}|{n_fmt}/{total_fmt}", leave=False, ascii=True if platform.system() == 'Windows' else None, dynamic_ncols=True, ) self.has_progress_display = True
def get_time_progression(self, run_time, n_iterations=None, override_skip_animations=False): if self.skip_animations and not override_skip_animations: times = [run_time] else: step = self.frame_duration times = np.arange(0, run_time, step) time_progression = ProgressDisplay( times, total=n_iterations, leave=self.leave_progress_bars, ) return time_progression
def get_time_progression(self, run_time, n_iterations=None, override_skip_animations=False): if self.skip_animations and not override_skip_animations: times = [run_time] else: step = 1 / self.camera.frame_rate times = np.arange(0, run_time, step) time_progression = ProgressDisplay( times, total=n_iterations, leave=self.leave_progress_bars, ascii=True if platform.system() == 'Windows' else None ) return time_progression
def get_time_progression(self, run_time, n_iterations=None, override_skip_animations=False): """ You will hardly use this when making your own animations. This method is for Manim's internal use. Returns a CommandLine ProgressBar whose fill_time is dependent on the run_time of an animation, the iterations to perform in that animation and a bool saying whether or not to consider the skipped animations. Parameters ---------- run_time: float The run_time of the animation. n_iterations: int, optional The number of iterations in the animation. override_skip_animations: bool, optional Whether or not to show skipped animations in the progress bar. Returns ------ ProgressDisplay The CommandLine Progress Bar. """ if file_writer_config[ "skip_animations"] and not override_skip_animations: times = [run_time] else: step = 1 / self.camera.frame_rate times = np.arange(0, run_time, step) time_progression = ProgressDisplay( times, total=n_iterations, leave=file_writer_config["leave_progress_bars"], ascii=True if platform.system() == "Windows" else None, disable=not file_writer_config["progress_bar"], ) return time_progression
def get_time_progression(self, run_time, n_iterations=None, override_skip_animations=False): """ You will hardly use this when making your own animations. This method is for Manim's internal use. Returns a CommandLine ProgressBar whose fill_time is dependent on the run_time of an animation, the iterations to perform in that animation and a bool saying whether or not to consider the skipped animations. Parameters ---------- run_time: Union[int,float] The run_time of the animation. n_iterations: None, int The number of iterations in the animation. override_skip_animations: bool (True) Whether or not to show skipped animations in the progress bar. Returns ------ ProgressDisplay The CommandLine Progress Bar. """ if self.skip_animations and not override_skip_animations: times = [run_time] else: step = 1 / self.camera.frame_rate times = np.arange(0, run_time, step) time_progression = ProgressDisplay( times, total=n_iterations, leave=self.leave_progress_bars, ascii=False if platform.system() != 'Windows' else True) return time_progression
def get_time_progression(self, run_time, n_iterations=None, desc="", override_skip_animations=False): if self.skip_animations and not override_skip_animations: return [run_time] else: step = 1 / self.camera.frame_rate times = np.arange(0, run_time, step) if self.file_writer.has_progress_display: self.file_writer.set_progress_display_subdescription(desc) return times return ProgressDisplay( times, total=n_iterations, leave=self.leave_progress_bars, ascii=True if platform.system() == 'Windows' else None, desc=desc, )
def play(self, *animations, **kwargs): self.num_animations += 1 if "run_time" in kwargs: run_time = kwargs["run_time"] else: run_time = animations[0].run_time for animation in animations: animation.set_run_time(run_time) moving_mobjects = [ mobject for anim in animations for mobject in anim.mobject.submobject_family() ] bundle = Mobject(*self.mobjects) static_mobjects = filter(lambda m: m not in moving_mobjects, bundle.submobject_family()) background = disp.paint_mobjects(static_mobjects, self.background, include_sub_mobjects=False) times = np.arange(0, run_time, self.frame_duration) time_progression = ProgressDisplay(times) time_progression.set_description( "Animation %d: "%self.num_animations + \ str(animations[0]) + \ (", etc." if len(animations) > 1 else "") ) for t in time_progression: for animation in animations: animation.update(t / animation.run_time) new_frame = disp.paint_mobjects( [anim.mobject for anim in animations], background) self.frames.append(new_frame) for animation in animations: animation.clean_up() self.add(*[anim.mobject for anim in animations]) self.repaint_mojects() return self
def construct(self): seconds = 60*5 droplets = Group(*[ PointDot(x*RIGHT+y*UP, radius = 0.15, density = 120) for x in range(-7, 9) for y in range(-3, 4) ]) droplets.set_color_by_gradient(BLUE, GREEN, YELLOW) self.use_function( lambda (x, y, z) : y*RIGHT+np.sin(2*np.pi*x)*UP, ) self.add(NumberPlane().fade()) self.play(ShowCreation(droplets)) n_steps = int(seconds * self.camera.frame_rate) from tqdm import tqdm as ProgressDisplay for x in ProgressDisplay(range(n_steps)): for d in droplets: if x%10 == 0: d.filter_out( lambda p : abs(p[0]) > 1.5*FRAME_X_RADIUS or abs(p[1]) > 1.5*FRAME_Y_RADIUS ) for p in d.points: p += 0.001*self.function(p) self.wait(1 / self.camera.frame_rate)
def get_time_progression(self, run_time): times = np.arange(0, run_time, self.frame_duration) time_progression = ProgressDisplay(times) return time_progression
def earclip_triangulation(verts: np.ndarray, ring_ends: list[int]) -> list: """ Returns a list of indices giving a triangulation of a polygon, potentially with holes - verts is a numpy array of points - ring_ends is a list of indices indicating where the ends of new paths are """ rings = [list(range(e0, e1)) for e0, e1 in zip([0, *ring_ends], ring_ends)] def is_in(point, ring_id): return abs( abs(get_winding_number([i - point for i in verts[rings[ring_id]]])) - 1) < 1e-5 def ring_area(ring_id): ring = rings[ring_id] s = 0 for i, j in zip(ring[1:], ring): s += cross2d(verts[i], verts[j]) return abs(s) / 2 # Points at the same position may cause problems for i in rings: verts[i[0]] += (verts[i[1]] - verts[i[0]]) * 1e-6 verts[i[-1]] += (verts[i[-2]] - verts[i[-1]]) * 1e-6 # First, we should know which rings are directly contained in it for each ring right = [max(verts[rings[i], 0]) for i in range(len(rings))] left = [min(verts[rings[i], 0]) for i in range(len(rings))] top = [max(verts[rings[i], 1]) for i in range(len(rings))] bottom = [min(verts[rings[i], 1]) for i in range(len(rings))] area = [ring_area(i) for i in range(len(rings))] # The larger ring must be outside rings_sorted = list(range(len(rings))) rings_sorted.sort(key=lambda x: area[x], reverse=True) def is_in_fast(ring_a, ring_b): # Whether a is in b return reduce( op.and_, (left[ring_b] <= left[ring_a] <= right[ring_a] <= right[ring_b], bottom[ring_b] <= bottom[ring_a] <= top[ring_a] <= top[ring_b], is_in(verts[rings[ring_a][0]], ring_b))) chilren = [[] for i in rings] ringenum = ProgressDisplay( enumerate(rings_sorted), total=len(rings), leave=False, ascii=True if platform.system() == 'Windows' else None, dynamic_ncols=True, desc="SVG Triangulation", delay=3, ) for idx, i in ringenum: for j in rings_sorted[:idx][::-1]: if is_in_fast(i, j): chilren[j].append(i) break res = [] # Then, we can use earcut for each part used = [False] * len(rings) for i in rings_sorted: if used[i]: continue v = rings[i] ring_ends = [len(v)] for j in chilren[i]: used[j] = True v += rings[j] ring_ends.append(len(v)) res += [v[i] for i in earcut(verts[v, :2], ring_ends)] return res