| class Compass(VGroup): | |
| def __init__(self, arm_length=3, arm_width=.2, angle=15*DEGREES, left_color=RED, right_color=YELLOW,): | |
| super().__init__() | |
| self.left_arm = Polygon( | |
| [0,0,0],[0,arm_length,0],[-arm_width,arm_length,0],[-arm_width,arm_width,0], | |
| stroke_width=0, | |
| fill_color=left_color, | |
| fill_opacity=1 | |
| ) | |
| self.right_arm = Polygon( | |
| [0,0,0],[0,arm_length,0],[arm_width,arm_length,0],[arm_width,arm_width,0], | |
| stroke_width=0, | |
| fill_color=right_color, | |
| fill_opacity=1 | |
| ) | |
| self.handle = VGroup( | |
| Circle(radius=2*arm_width), | |
| Rectangle(width=arm_width,height=4*arm_width).shift([0,2*arm_width,0]) | |
| ).set_stroke(width=0).set_fill(color=WHITE,opacity=1) | |
| self.handle.shift(self.get_pivot()) | |
| self.set_angle(angle=angle) | |
| self.add(self.left_arm, self.right_arm, self.handle) | |
| def get_left_point(self): | |
| return self.left_arm.get_vertices()[0] | |
| def get_right_point(self): | |
| return self.right_arm.get_vertices()[0] | |
| def get_pivot(self): | |
| return self.right_arm.get_vertices()[1] | |
| def set_angle(self, angle=15*DEGREES): | |
| curr_langle = Line(self.left_arm.get_vertices()[0],self.left_arm.get_vertices()[1]).get_angle() | |
| curr_rangle = Line(self.right_arm.get_vertices()[0],self.right_arm.get_vertices()[1]).get_angle() | |
| curr_angle = curr_rangle-curr_langle | |
| self.left_arm.rotate(angle=curr_angle/2-angle/2,about_point=self.get_left_point()) | |
| self.right_arm.rotate(angle=-curr_angle/2+angle/2,about_point=self.right_arm.get_vertices()[1]) | |
| self.right_arm.shift(self.left_arm.get_vertices()[1]-self.right_arm.get_vertices()[1]) | |
| self.handle.shift(self.left_arm.get_vertices()[1]-self.handle[0].get_center()) | |
| def set_width(self, width=5): | |
| angle = np.asin(0.5*width/np.linalg.norm(self.left_arm.get_vertices()[1]-self.left_arm.get_vertices()[0])) | |
| self.set_angle(angle=2*angle) | |
| class CompassDemo(Scene): | |
| def construct(self): | |
| self.add(NumberPlane()) | |
| cmp = Compass(angle=40*DEGREES) | |
| self.add(cmp) | |
| self.wait() | |
| self.play(Rotate(cmp,-40*DEGREES,about_point=ORIGIN)) | |
| self.wait() | |
| self.play(cmp.animate.set_angle(30*DEGREES)) | |
| self.wait() | |
| self.play(Rotate(cmp,40*DEGREES,about_point=ORIGIN)) | |
| self.wait() | |
| self.play(cmp.animate.set_width(3)) | |
| self.wait() | |
| tp = TracedPath( | |
| cmp.get_right_point | |
| ) | |
| self.add(tp) | |
| self.play( | |
| Rotate(cmp,2*PI,about_point=cmp.get_left_point()), | |
| run_time=3, | |
| rate_func=rate_functions.linear | |
| ) | |
| self.wait() |