class Tracked_Point(VGroup): CONFIG = { 'size': 0.1, 'point_color': BLUE, 'num_decimal_places': 2, 'coordinates_scale': 0.8, 'coordinates_color': GREEN, 'coordinates_direction': DOWN * 0.25, 'bracket_color': WHITE, } def __init__(self, init_loc=ORIGIN, **kwargs): VGroup.__init__(self, **kwargs) self.point = Dot(init_loc, color=self.point_color).set_height(self.size) self.value_x = DecimalNumber(0, color=self.coordinates_color, num_decimal_places=self.num_decimal_places).scale(self.coordinates_scale) self.value_y = DecimalNumber(0, color=self.coordinates_color, num_decimal_places=self.num_decimal_places).scale(self.coordinates_scale) text = TexMobject('(', ',', ')').scale(self.coordinates_scale) self.coordinates_text = VGroup(text[0], self.value_x, text[1], self.value_y, text[2]) self.coordinates_text.add_updater(self.update_coordinates_text) self.add(self.point) def update_coordinates_text(self, coords): for i in range(1, len(coords)): coords[i].next_to(coords[i-1], RIGHT * 0.5) coords[2].align_to(coords[1], DOWN) pos = self.point.get_center() x, y = self.mapping_func(pos[0], pos[1]) coords[1].set_value(x) coords[3].set_value(y) coords.next_to(self.point, self.coordinates_direction) def mapping_func(self, x, y): return x, y
def create_lines(self): lines = VGroup() for angle in np.arange(0, TAU, TAU / self.num_lines): line = Line(ORIGIN, self.line_length * RIGHT) line.shift((self.flash_radius - self.line_length) * RIGHT) line.rotate(angle, about_point=ORIGIN) lines.add(line) lines.set_stroke(color=self.color, width=self.line_stroke_width) lines.add_updater(lambda l: l.move_to(self.point)) return lines
def get_cursor_location_label(self): decimals = VGroup(*(DecimalNumber(**self.cursor_location_config) for n in range(3))) def update_coords(decimals): for mob, coord in zip(decimals, self.mouse_point.get_location()): mob.set_value(coord) decimals.arrange(RIGHT, buff=decimals.get_height()) decimals.to_corner(DR, buff=SMALL_BUFF) decimals.fix_in_frame() return decimals decimals.add_updater(update_coords) return decimals
def get_information_label(self): loc_label = VGroup(*(DecimalNumber(**self.cursor_location_config) for n in range(3))) def update_coords(loc_label): for mob, coord in zip(loc_label, self.mouse_point.get_location()): mob.set_value(coord) loc_label.arrange(RIGHT, buff=loc_label.get_height()) loc_label.to_corner(DR, buff=SMALL_BUFF) loc_label.fix_in_frame() return loc_label loc_label.add_updater(update_coords) time_label = DecimalNumber(0, **self.time_label_config) time_label.to_corner(DL, buff=SMALL_BUFF) time_label.fix_in_frame() time_label.add_updater(lambda m, dt: m.increment_value(dt)) return VGroup(loc_label, time_label)
class Trail(VGroup): CONFIG = { 'max_width': 5, 'nums': 500, 'trail_color': BLUE_B, # 'rate_func': linear, 'rate_func': lambda t: t**1.25, } def __init__(self, mob, **kwargs): VGroup.__init__(self, **kwargs) self.add(mob) self.trail = VGroup() self.path_xyz = [] self.add(self.trail) self.pos_old = self[0].get_center() if type(self.trail_color) != str: self.colors = color_gradient(self.trail_color, self.nums) # def update_trail(self, trail): # err=1e-5 # pos_new = self[0].get_center() # pos_old = self.pos_old # self.pos_old = pos_new # # if np.sqrt(sum((pos_new - pos_old) ** 2))>err: # if sum(abs(pos_new - pos_old))>err: # trail.add(Line(pos_old, pos_new, color=self.trail_color, plot_depth=0)) # # if len(trail) > self.nums: # trail.remove(trail[0]) # # for k in range(self.nums): # # trail[k].set_stroke(width=self.max_width * self.rate_func(k/self.nums), # # opacity=self.rate_func(k/self.nums)) # for l in trail: # k = trail.submobjects.index(l) # l.set_stroke(width=self.max_width * self.rate_func(k/self.nums), # opacity=self.rate_func(k/self.nums)) # # if len(trail) <= self.nums and len(trail) > 0: # # for k in range(len(trail)): # # trail[k].set_stroke(width=self.max_width * self.rate_func(k/len(trail)), # # opacity=self.rate_func(k/len(trail))) # for l in trail: # k = trail.submobjects.index(l) # l.set_stroke(width=self.max_width * self.rate_func(k/len(trail)), # opacity=self.rate_func(k/len(trail))) def get_path_xyz(self, err=1e-6): pos_new = self[0].get_center() pos_old = self.pos_old if sum(abs(pos_new - pos_old)) > err: self.path_xyz.append(pos_new) self.pos_old = pos_new while len(self.path_xyz) > self.nums: self.path_xyz.remove(self.path_xyz[0]) def create_path(self): path = VGroup() self.get_path_xyz() if len(self.path_xyz) > 1: for i in range(len(self.path_xyz) - 1): if type(self.trail_color) == str: path.add( Line(self.path_xyz[i], self.path_xyz[i + 1], stroke_color=self.trail_color, stroke_opacity=self.rate_func(i / len(self.path_xyz)), plot_depth=self.rate_func(2 - i / len(self.path_xyz)), stroke_width=self.max_width * self.rate_func(i / len(self.path_xyz)))) else: path.add( Line(self.path_xyz[i], self.path_xyz[i + 1], stroke_color=self.colors[i], stroke_opacity=self.rate_func(i / len(self.path_xyz)), plot_depth=self.rate_func(2 - i / len(self.path_xyz)), stroke_width=self.max_width * self.rate_func(i / len(self.path_xyz)))) # print('i = %d' % i) # # print(self.path_xyz) # print(self.color) # print(self.rate_func(i/len(self.path_xyz))) # print(self.max_width*self.rate_func(i/len(self.path_xyz))) return path def update_path(self, trail): trail.become(self.create_path()) def start_trace(self): # self.trail.add_updater(self.update_trail) self.trail.add_updater(self.update_path) def stop_trace(self): self.trial.remove_updater(self.update_path) def decrease_trail_num(self, trail, dt): if self.nums > max(self.min_num, 2): if self.nums <= 2: trail.become(VGroup()) else: self.nums -= self.rate if self.nums < 2: self.nums = 2 trail.become(self.create_path()) def retrieve_trail(self, rate=2, min_num=0): # self.stop_trace() self.nums = len(self.trail) self.min_num = min_num self.rate = rate self.trail.add_updater(self.decrease_trail_num)
class Trail(VGroup): CONFIG = { 'max_width': 5, 'nums': 500, 'trail_color': BLUE_B, # 'rate_func': linear, 'rate_func': lambda t: t**1.25, } def __init__(self, mob, **kwargs): VGroup.__init__(self, **kwargs) self.add(mob) self.trail = VGroup() self.path_xyz = [] self.add(self.trail) self.pos_old = self[0].get_center() def update_trail(self, trail): err = 1e-9 pos_new = self[0].get_center() pos_old = self.pos_old self.pos_old = pos_new # if np.sqrt(sum((pos_new - pos_old) ** 2))>err: if sum(abs(pos_new - pos_old)) > err: trail.add( Line(pos_old, pos_new, color=self.trail_color, plot_depth=0)) if len(trail) > self.nums: trail.remove(trail[0]) # for k in range(self.nums): # trail[k].set_stroke(width=self.max_width * self.rate_func(k/self.nums), # opacity=self.rate_func(k/self.nums)) for l in trail: k = trail.submobjects.index(l) l.set_stroke(width=self.max_width * self.rate_func(k / self.nums), opacity=self.rate_func(k / self.nums)) if len(trail) <= self.nums and len(trail) > 0: # for k in range(len(trail)): # trail[k].set_stroke(width=self.max_width * self.rate_func(k/len(trail)), # opacity=self.rate_func(k/len(trail))) for l in trail: k = trail.submobjects.index(l) l.set_stroke(width=self.max_width * self.rate_func(k / len(trail)), opacity=self.rate_func(k / len(trail))) def get_path_xyz(self, err=1e-9): pos_new = self[0].get_center() pos_old = self.pos_old if sum(abs(pos_new - pos_old)) > err: self.path_xyz.append(pos_new) self.pos_old = pos_new while len(self.path_xyz) > self.nums: self.path_xyz.remove(self.path_xyz[0]) def create_path(self): path = VGroup() self.get_path_xyz() if len(self.path_xyz) > 1: for i in range(len(self.path_xyz) - 1): path.add( Line(self.path_xyz[i], self.path_xyz[i + 1], stroke_color=self.trail_color, stroke_opacity=self.rate_func(i / len(self.path_xyz)), plot_depth=self.rate_func(i / len(self.path_xyz)), stroke_width=self.max_width * self.rate_func(i / len(self.path_xyz)))) # print('i = %d' % i) # # print(self.path_xyz) # print(self.color) # print(self.rate_func(i/len(self.path_xyz))) # print(self.max_width*self.rate_func(i/len(self.path_xyz))) return path def update_path(self, trail): trail.become(self.create_path()) def start_trace(self): # self.trail.add_updater(self.update_trail) self.trail.add_updater(self.update_path)