mirror of
https://github.com/3b1b/manim.git
synced 2025-04-13 09:47:07 +00:00
139 lines
4.1 KiB
Python
139 lines
4.1 KiB
Python
from big_ol_pile_of_manim_imports import *
|
|
|
|
|
|
class SlidingBlocks(VGroup):
|
|
CONFIG = {
|
|
"block_dynamic_configs": [
|
|
{
|
|
"mass": 100,
|
|
"velocity": -2,
|
|
"distance": 7,
|
|
"width": 1,
|
|
},
|
|
{
|
|
"mass": 1,
|
|
"velocity": 0,
|
|
"distance": 3,
|
|
"width": 1,
|
|
},
|
|
],
|
|
"block_style": {
|
|
"fill_opacity": 1,
|
|
"fill_color": (GREY, LIGHT_GREY),
|
|
"stroke_width": 3,
|
|
"stroke_color": WHITE,
|
|
}
|
|
}
|
|
|
|
def __init__(self, surrounding_scene, **kwargs):
|
|
VGroup.__init__(self, **kwargs)
|
|
self.surrounding_scene = surrounding_scene
|
|
self.floor = surrounding_scene.floor
|
|
self.wall = surrounding_scene.wall
|
|
|
|
for config in self.block_dynamic_configs:
|
|
self.add(self.get_block(**config))
|
|
self.add_updater(self.__class__.update_positions)
|
|
|
|
def get_block(self, mass, width, distance, velocity):
|
|
block = Square(side_length=width)
|
|
block.set_style(**self.block_style)
|
|
block.move_to(
|
|
self.floor.get_top()[1] * UP +
|
|
(self.wall.get_right()[0] + distance) * RIGHT,
|
|
DL,
|
|
)
|
|
block.mass = mass
|
|
block.velocity = velocity
|
|
label = block.label = TextMobject("{}kg".format(mass))
|
|
label.scale(0.8)
|
|
label.next_to(block, UP, SMALL_BUFF)
|
|
block.add(label)
|
|
return block
|
|
|
|
def update_positions(self, dt):
|
|
blocks = self.submobjects
|
|
for block in blocks:
|
|
block.shift(block.velocity * dt * RIGHT)
|
|
if blocks[0].get_left()[0] < blocks[1].get_right()[0]:
|
|
# Two blocks collide
|
|
m1 = blocks[0].mass
|
|
m2 = blocks[1].mass
|
|
v1 = blocks[0].velocity
|
|
v2 = blocks[1].velocity
|
|
v_phase_space_point = np.array([
|
|
np.sqrt(m1) * v1, -np.sqrt(m2) * v2
|
|
])
|
|
angle = 2 * np.arctan(np.sqrt(m2 / m1))
|
|
new_vps_point = rotate_vector(v_phase_space_point, angle)
|
|
for block, value in zip(blocks, new_vps_point):
|
|
block.velocity = value / np.sqrt(block.mass)
|
|
blocks[1].move_to(blocks[0].get_corner(DL), DR)
|
|
self.surrounding_scene.clack(blocks[0].get_left())
|
|
if blocks[1].get_left()[0] < self.wall.get_right()[0]:
|
|
# Second block hits wall
|
|
blocks[1].velocity *= -1
|
|
blocks[1].move_to(self.wall.get_corner(DR), DL)
|
|
self.surrounding_scene.clack(blocks[1].get_left())
|
|
return self
|
|
|
|
|
|
class BlocksAndWallScene(Scene):
|
|
CONFIG = {
|
|
"print_clack_times": True,
|
|
"sliding_blocks_config": {},
|
|
"floor_y": -2,
|
|
"wall_x": -5,
|
|
}
|
|
|
|
def setup(self):
|
|
self.floor = self.get_floor()
|
|
self.wall = self.get_wall()
|
|
self.blocks = SlidingBlocks(self)
|
|
self.clack_times = []
|
|
time_tracker = ValueTracker()
|
|
time_tracker.add_updater(lambda m, dt: m.increment_value(dt))
|
|
self.add(time_tracker)
|
|
self.get_time = time_tracker.get_value
|
|
|
|
self.add(self.floor, self.wall, self.blocks)
|
|
|
|
def tear_down(self):
|
|
if self.print_clack_times:
|
|
print(self.clack_times)
|
|
|
|
def get_wall(self):
|
|
wall = Line(self.floor_y * UP, FRAME_HEIGHT * UP / 2)
|
|
wall.shift(self.wall_x * RIGHT)
|
|
lines = VGroup(*[
|
|
Line(ORIGIN, 0.25 * UR)
|
|
for x in range(15)
|
|
])
|
|
lines.set_stroke(width=1)
|
|
lines.arrange_submobjects(UP, buff=MED_SMALL_BUFF)
|
|
lines.move_to(wall, DR)
|
|
wall.add(lines)
|
|
return wall
|
|
|
|
def get_floor(self):
|
|
floor = Line(self.wall_x * RIGHT, FRAME_WIDTH * RIGHT / 2)
|
|
floor.shift(self.floor_y * UP)
|
|
return floor
|
|
|
|
def get_blocks(self):
|
|
pass
|
|
|
|
def clack(self, location):
|
|
self.clack_times.append(self.get_time())
|
|
|
|
|
|
# Animted scenes
|
|
|
|
class MathAndPhysicsConspiring(Scene):
|
|
def construct(self):
|
|
pass
|
|
|
|
|
|
class ThreeSimpleClacks(BlocksAndWallScene):
|
|
def construct(self):
|
|
self.wait(10)
|