mirror of
https://github.com/3b1b/manim.git
synced 2025-11-16 01:47:50 +00:00
Most of BlocksAndWallScene is setup
This commit is contained in:
parent
d222c8aa14
commit
0c810b43a9
1 changed files with 130 additions and 26 deletions
|
|
@ -3,25 +3,24 @@ from big_ol_pile_of_manim_imports import *
|
||||||
|
|
||||||
class SlidingBlocks(VGroup):
|
class SlidingBlocks(VGroup):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"block_dynamic_configs": [
|
"block1_config": {
|
||||||
{
|
"mass": 1,
|
||||||
"mass": 100,
|
|
||||||
"velocity": -2,
|
"velocity": -2,
|
||||||
"distance": 7,
|
"distance": 7,
|
||||||
"width": 1,
|
"width": 1,
|
||||||
},
|
},
|
||||||
{
|
"block2_config": {
|
||||||
"mass": 1,
|
"mass": 1,
|
||||||
"velocity": 0,
|
"velocity": 0,
|
||||||
"distance": 3,
|
"distance": 3,
|
||||||
"width": 1,
|
"width": 1,
|
||||||
},
|
},
|
||||||
],
|
|
||||||
"block_style": {
|
"block_style": {
|
||||||
"fill_opacity": 1,
|
"fill_opacity": 1,
|
||||||
"fill_color": (GREY, LIGHT_GREY),
|
"fill_color": (GREY, LIGHT_GREY),
|
||||||
"stroke_width": 3,
|
"stroke_width": 3,
|
||||||
"stroke_color": WHITE,
|
"stroke_color": WHITE,
|
||||||
|
"sheen_direction": UL,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -31,27 +30,69 @@ class SlidingBlocks(VGroup):
|
||||||
self.floor = surrounding_scene.floor
|
self.floor = surrounding_scene.floor
|
||||||
self.wall = surrounding_scene.wall
|
self.wall = surrounding_scene.wall
|
||||||
|
|
||||||
for config in self.block_dynamic_configs:
|
self.block1 = self.get_block(**self.block1_config)
|
||||||
self.add(self.get_block(**config))
|
self.block2 = self.get_block(**self.block2_config)
|
||||||
|
self.phase_space_point_tracker = self.get_phase_space_point_tracker()
|
||||||
|
self.add(
|
||||||
|
self.block1, self.block2,
|
||||||
|
self.phase_space_point_tracker,
|
||||||
|
)
|
||||||
self.add_updater(self.__class__.update_positions)
|
self.add_updater(self.__class__.update_positions)
|
||||||
|
|
||||||
|
# From here, there's enough information to create
|
||||||
|
# a list of all clack times and locations
|
||||||
|
|
||||||
def get_block(self, mass, width, distance, velocity):
|
def get_block(self, mass, width, distance, velocity):
|
||||||
block = Square(side_length=width)
|
block = Square(side_length=width)
|
||||||
|
block.mass = mass
|
||||||
|
block.velocity = velocity
|
||||||
|
|
||||||
block.set_style(**self.block_style)
|
block.set_style(**self.block_style)
|
||||||
|
block.set_fill(color=interpolate_color(
|
||||||
|
block.get_fill_color(),
|
||||||
|
BLUE_E,
|
||||||
|
(1 - 1.0 / (max(np.log10(mass), 1)))
|
||||||
|
))
|
||||||
block.move_to(
|
block.move_to(
|
||||||
self.floor.get_top()[1] * UP +
|
self.floor.get_top()[1] * UP +
|
||||||
(self.wall.get_right()[0] + distance) * RIGHT,
|
(self.wall.get_right()[0] + distance) * RIGHT,
|
||||||
DL,
|
DL,
|
||||||
)
|
)
|
||||||
block.mass = mass
|
label = block.label = TextMobject(
|
||||||
block.velocity = velocity
|
"{:,}\\,kg".format(mass)
|
||||||
label = block.label = TextMobject("{}kg".format(mass))
|
)
|
||||||
label.scale(0.8)
|
label.scale(0.8)
|
||||||
label.next_to(block, UP, SMALL_BUFF)
|
label.next_to(block, UP, SMALL_BUFF)
|
||||||
block.add(label)
|
block.add(label)
|
||||||
return block
|
return block
|
||||||
|
|
||||||
|
def get_phase_space_point_tracker(self):
|
||||||
|
block1, block2 = self.block1, self.block2
|
||||||
|
w2 = block2.get_width()
|
||||||
|
s1 = block1.get_left()[0] - self.wall.get_right()[0] - w2
|
||||||
|
s2 = block2.get_right()[0] - self.wall.get_right()[0] - w2
|
||||||
|
result = VectorizedPoint([
|
||||||
|
s1 * np.sqrt(block1.mass),
|
||||||
|
s2 * np.sqrt(block2.mass),
|
||||||
|
0
|
||||||
|
])
|
||||||
|
|
||||||
|
result.velocity = np.array([
|
||||||
|
np.sqrt(block1.mass) * block1.velocity,
|
||||||
|
np.sqrt(block2.mass) * block2.velocity,
|
||||||
|
0
|
||||||
|
])
|
||||||
|
return result
|
||||||
|
|
||||||
def update_positions(self, dt):
|
def update_positions(self, dt):
|
||||||
|
self.phase_space_point_tracker.shift(
|
||||||
|
self.phase_space_point_tracker.velocity * dt
|
||||||
|
)
|
||||||
|
self.update_blocks_from_phase_space_point_tracker()
|
||||||
|
|
||||||
|
def old_update_positions(self, dt):
|
||||||
|
# Based on velocity diagram bouncing...didn't work for
|
||||||
|
# large masses, due to frame rate mismatch
|
||||||
blocks = self.submobjects
|
blocks = self.submobjects
|
||||||
for block in blocks:
|
for block in blocks:
|
||||||
block.shift(block.velocity * dt * RIGHT)
|
block.shift(block.velocity * dt * RIGHT)
|
||||||
|
|
@ -74,13 +115,45 @@ class SlidingBlocks(VGroup):
|
||||||
# Second block hits wall
|
# Second block hits wall
|
||||||
blocks[1].velocity *= -1
|
blocks[1].velocity *= -1
|
||||||
blocks[1].move_to(self.wall.get_corner(DR), DL)
|
blocks[1].move_to(self.wall.get_corner(DR), DL)
|
||||||
|
if blocks[0].get_left()[0] < blocks[1].get_right()[0]:
|
||||||
|
blocks[0].move_to(blocks[1].get_corner(DR), DL)
|
||||||
self.surrounding_scene.clack(blocks[1].get_left())
|
self.surrounding_scene.clack(blocks[1].get_left())
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
def update_blocks_from_phase_space_point_tracker(self):
|
||||||
|
block1, block2 = self.block1, self.block2
|
||||||
|
|
||||||
|
ps_point = self.phase_space_point_tracker.get_location()
|
||||||
|
theta = np.arctan(np.sqrt(block2.mass / block1.mass))
|
||||||
|
ps_point_angle = angle_of_vector(ps_point)
|
||||||
|
n_clacks = int(ps_point_angle / theta)
|
||||||
|
# TODO, pass on n_clack information to surrounding_scene
|
||||||
|
reflected_point = rotate_vector(
|
||||||
|
ps_point,
|
||||||
|
-2 * np.ceil(n_clacks / 2) * theta
|
||||||
|
)
|
||||||
|
reflected_point = np.abs(reflected_point)
|
||||||
|
|
||||||
|
shadow_wall_x = self.wall.get_right()[0] + block2.get_width()
|
||||||
|
floor_y = self.floor.get_top()[1]
|
||||||
|
s1 = reflected_point[0] / np.sqrt(block1.mass)
|
||||||
|
s2 = reflected_point[1] / np.sqrt(block2.mass)
|
||||||
|
block1.move_to(
|
||||||
|
(shadow_wall_x + s1) * RIGHT +
|
||||||
|
floor_y * UP,
|
||||||
|
DL,
|
||||||
|
)
|
||||||
|
block2.move_to(
|
||||||
|
(shadow_wall_x + s2) * RIGHT +
|
||||||
|
floor_y * UP,
|
||||||
|
DR,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class BlocksAndWallScene(Scene):
|
class BlocksAndWallScene(Scene):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"print_clack_times": True,
|
"print_clack_times": False,
|
||||||
|
"count_clacks": True,
|
||||||
"sliding_blocks_config": {},
|
"sliding_blocks_config": {},
|
||||||
"floor_y": -2,
|
"floor_y": -2,
|
||||||
"wall_x": -5,
|
"wall_x": -5,
|
||||||
|
|
@ -89,14 +162,36 @@ class BlocksAndWallScene(Scene):
|
||||||
def setup(self):
|
def setup(self):
|
||||||
self.floor = self.get_floor()
|
self.floor = self.get_floor()
|
||||||
self.wall = self.get_wall()
|
self.wall = self.get_wall()
|
||||||
self.blocks = SlidingBlocks(self)
|
self.blocks = SlidingBlocks(self, **self.sliding_blocks_config)
|
||||||
|
self.add(self.floor, self.wall, self.blocks)
|
||||||
|
if self.count_clacks:
|
||||||
|
self.add_clack_counter()
|
||||||
|
|
||||||
|
self.track_times()
|
||||||
|
|
||||||
|
def track_times(self):
|
||||||
self.clack_times = []
|
self.clack_times = []
|
||||||
time_tracker = ValueTracker()
|
time_tracker = ValueTracker()
|
||||||
time_tracker.add_updater(lambda m, dt: m.increment_value(dt))
|
time_tracker.add_updater(lambda m, dt: m.increment_value(dt))
|
||||||
self.add(time_tracker)
|
self.add(time_tracker)
|
||||||
self.get_time = time_tracker.get_value
|
self.get_time = time_tracker.get_value
|
||||||
|
|
||||||
self.add(self.floor, self.wall, self.blocks)
|
def add_clack_counter(self):
|
||||||
|
clack_counter_label = TextMobject("\\# Clacks: ")
|
||||||
|
clack_counter = Integer(0)
|
||||||
|
clack_counter.next_to(
|
||||||
|
clack_counter_label[-1], RIGHT,
|
||||||
|
aligned_edge=DOWN,
|
||||||
|
)
|
||||||
|
clack_group = VGroup(
|
||||||
|
clack_counter_label,
|
||||||
|
clack_counter,
|
||||||
|
)
|
||||||
|
clack_group.to_corner(UR)
|
||||||
|
clack_group.shift(LEFT)
|
||||||
|
self.add(clack_group)
|
||||||
|
|
||||||
|
self.clack_counter = clack_counter
|
||||||
|
|
||||||
def tear_down(self):
|
def tear_down(self):
|
||||||
if self.print_clack_times:
|
if self.print_clack_times:
|
||||||
|
|
@ -120,11 +215,10 @@ class BlocksAndWallScene(Scene):
|
||||||
floor.shift(self.floor_y * UP)
|
floor.shift(self.floor_y * UP)
|
||||||
return floor
|
return floor
|
||||||
|
|
||||||
def get_blocks(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def clack(self, location):
|
def clack(self, location):
|
||||||
self.clack_times.append(self.get_time())
|
self.clack_times.append(self.get_time())
|
||||||
|
if self.count_clacks:
|
||||||
|
self.clack_counter.increment_value()
|
||||||
|
|
||||||
|
|
||||||
# Animted scenes
|
# Animted scenes
|
||||||
|
|
@ -135,5 +229,15 @@ class MathAndPhysicsConspiring(Scene):
|
||||||
|
|
||||||
|
|
||||||
class ThreeSimpleClacks(BlocksAndWallScene):
|
class ThreeSimpleClacks(BlocksAndWallScene):
|
||||||
|
CONFIG = {
|
||||||
|
"sliding_blocks_config": {
|
||||||
|
"block1_config": {
|
||||||
|
"mass": 100,
|
||||||
|
"width": 1.5,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
def construct(self):
|
def construct(self):
|
||||||
self.wait(10)
|
while self.blocks[0].get_left()[0] < FRAME_WIDTH / 2:
|
||||||
|
self.wait(1)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue