mirror of
https://github.com/3b1b/manim.git
synced 2025-07-31 22:13:30 +08:00
first variants of generalized Pascal's Triangle
This commit is contained in:
@ -1,201 +1,351 @@
|
||||
from big_ol_pile_of_manim_imports import *
|
||||
from once_useful_constructs.combinatorics import *
|
||||
|
||||
nb_levels = 50
|
||||
nb_levels = 5
|
||||
|
||||
dev_x_step = 2
|
||||
dev_y_step = 5
|
||||
|
||||
def rainbow_color(alpha):
|
||||
nb_colors = 100
|
||||
rainbow = color_gradient([RED, ORANGE, YELLOW, GREEN, BLUE, PURPLE], nb_colors)
|
||||
rainbow = np.append(rainbow,PURPLE)
|
||||
index = int(alpha * nb_colors)
|
||||
return rainbow[index]
|
||||
nb_colors = 100
|
||||
rainbow = color_gradient([RED, ORANGE, YELLOW, GREEN, BLUE, PURPLE], nb_colors)
|
||||
rainbow = np.append(rainbow,PURPLE)
|
||||
index = int(alpha * nb_colors)
|
||||
return rainbow[index]
|
||||
|
||||
def graded_color(n,k):
|
||||
if n != 0:
|
||||
alpha = float(k)/n
|
||||
else:
|
||||
alpha = 0.5
|
||||
color = interpolate_color(RED, BLUE, alpha)
|
||||
return color
|
||||
|
||||
|
||||
class SampleScene(Scene):
|
||||
def graded_square(n,k):
|
||||
return Square(
|
||||
side_length = 1,
|
||||
fill_color = graded_color(n,k),
|
||||
fill_opacity = 1,
|
||||
stroke_width = 1
|
||||
)
|
||||
|
||||
def construct(self):
|
||||
def graded_binomial(n,k):
|
||||
return Integer(
|
||||
choose(n,k),
|
||||
color = graded_color(n,k)
|
||||
)
|
||||
|
||||
triangle = Polygon()
|
||||
self.add(triangle)
|
||||
self.wait()
|
||||
def split_square(n,k):
|
||||
width = 1
|
||||
height = 1
|
||||
|
||||
proportion = float(choose(n,k)) / 2**n
|
||||
|
||||
lower_height = proportion * height
|
||||
upper_height = (1 - proportion) * height
|
||||
lower_rect = Rectangle(
|
||||
width = width,
|
||||
height = lower_height,
|
||||
fill_color = RED,
|
||||
fill_opacity = 1.0,
|
||||
stroke_color = WHITE,
|
||||
stroke_width = 3
|
||||
)
|
||||
upper_rect = Rectangle(
|
||||
width = width,
|
||||
height = upper_height,
|
||||
fill_color = BLUE,
|
||||
fill_opacity = 1.0,
|
||||
stroke_color = WHITE,
|
||||
stroke_width = 3
|
||||
)
|
||||
upper_rect.next_to(lower_rect,UP,buff = 0)
|
||||
square = VGroup(lower_rect, upper_rect).move_to(ORIGIN)
|
||||
return square
|
||||
|
||||
|
||||
class BuildNewPascalRow(Transform):
|
||||
|
||||
def __init__(self,mobject, duplicate_row = None, **kwargs):
|
||||
if mobject.__class__ != GeneralizedPascalsTriangle and mobject.__class__ != PascalsTriangle:
|
||||
raise("Transform BuildNewPascalRow only works on members of (Generalized)PascalsTriangle!")
|
||||
|
||||
n = mobject.nrows - 1
|
||||
lowest_row_copy1 = mobject.get_lowest_row()
|
||||
lowest_row_copy2 = duplicate_row
|
||||
|
||||
start_mob = VGroup(lowest_row_copy1, lowest_row_copy2)
|
||||
|
||||
new_pt = mobject.copy()
|
||||
new_pt.nrows += 1
|
||||
new_pt.generate_points()
|
||||
# align with original (copy got centered on screen)
|
||||
c1 = new_pt.coords_to_mobs[0][0].get_center()
|
||||
c2 = mobject.coords_to_mobs[0][0].get_center()
|
||||
print c1, c2
|
||||
v = c2 - c1
|
||||
new_pt.shift(v)
|
||||
|
||||
new_row_left_copy = VGroup(*[
|
||||
new_pt.coords_to_mobs[n+1][k]
|
||||
for k in range(0,n+1)
|
||||
])
|
||||
|
||||
new_row_right_copy = VGroup(*[
|
||||
new_pt.coords_to_mobs[n+1][k]
|
||||
for k in range(1,n+2)
|
||||
]).copy()
|
||||
|
||||
target_mob = VGroup(new_row_left_copy, new_row_right_copy)
|
||||
|
||||
Transform.__init__(self, start_mob, target_mob, **kwargs)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class SimplePascal(Scene):
|
||||
|
||||
def build_new_pascal_row(self,old_pt):
|
||||
|
||||
lowest_row_copy = old_pt.get_lowest_row().copy()
|
||||
self.add(lowest_row_copy)
|
||||
|
||||
n = old_pt.nrows - 1
|
||||
lowest_row_copy1 = old_pt.get_lowest_row()
|
||||
lowest_row_copy2 = lowest_row_copy1.copy()
|
||||
|
||||
|
||||
start_mob = VGroup(lowest_row_copy1, lowest_row_copy2)
|
||||
self.add(start_mob)
|
||||
|
||||
new_pt = old_pt.copy()
|
||||
cell_height = old_pt.height / old_pt.nrows
|
||||
cell_width = old_pt.width / old_pt.nrows
|
||||
new_pt.nrows += 1
|
||||
new_pt.height = new_pt.nrows * cell_height
|
||||
new_pt.width = new_pt.nrows * cell_width
|
||||
|
||||
new_pt.generate_points()
|
||||
# align with original (copy got centered on screen)
|
||||
c1 = new_pt.coords_to_mobs[0][0].get_center()
|
||||
c2 = old_pt.coords_to_mobs[0][0].get_center()
|
||||
v = c2 - c1
|
||||
new_pt.shift(v)
|
||||
|
||||
new_row_left_copy = VGroup(*[
|
||||
new_pt.coords_to_mobs[n+1][k]
|
||||
for k in range(0,n+1)
|
||||
])
|
||||
|
||||
new_row_right_copy = VGroup(*[
|
||||
new_pt.coords_to_mobs[n+1][k]
|
||||
for k in range(1,n+2)
|
||||
]).copy()
|
||||
|
||||
target_mob = VGroup(new_row_left_copy, new_row_right_copy)
|
||||
self.play(Transform(start_mob, target_mob))
|
||||
|
||||
return new_pt
|
||||
|
||||
|
||||
|
||||
def construct(self):
|
||||
|
||||
cell_height = 1
|
||||
cell_width = 1
|
||||
nrows = 1
|
||||
pt = GeneralizedPascalsTriangle(
|
||||
nrows = nrows,
|
||||
height = nrows * cell_height,
|
||||
width = nrows * cell_width,
|
||||
submob_class = graded_square,
|
||||
portion_to_fill = 0.9
|
||||
)
|
||||
pt.shift(3 * UP)
|
||||
self.add(pt)
|
||||
lowest_row_copy = pt.get_lowest_row().copy()
|
||||
self.add(lowest_row_copy)
|
||||
#self.play(BuildNewPascalRow(pt, duplicate_row = lowest_row_copy))
|
||||
for i in range(7):
|
||||
pt = self.build_new_pascal_row(pt)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class PascalNetScene(Scene):
|
||||
|
||||
def construct(self):
|
||||
def construct(self):
|
||||
|
||||
unit_width = 0.25
|
||||
top_height = 4.0
|
||||
level_height = 2.0 * top_height / nb_levels
|
||||
unit_width = 0.25
|
||||
top_height = 4.0
|
||||
level_height = 2.0 * top_height / nb_levels
|
||||
|
||||
start_points = np.array([top_height * UP])
|
||||
start_points = np.array([top_height * UP])
|
||||
|
||||
dev_start = start_points[0]
|
||||
dev_start = start_points[0]
|
||||
|
||||
j = 0
|
||||
j = 0
|
||||
|
||||
for n in range(nb_levels):
|
||||
for n in range(nb_levels):
|
||||
|
||||
half_width = 0.5 * (n + 0.5) * unit_width
|
||||
half_width = 0.5 * (n + 0.5) * unit_width
|
||||
|
||||
stop_points_left = start_points.copy()
|
||||
stop_points_left[:,0] -= 0.5 * unit_width
|
||||
stop_points_left[:,1] -= level_height
|
||||
stop_points_left = start_points.copy()
|
||||
stop_points_left[:,0] -= 0.5 * unit_width
|
||||
stop_points_left[:,1] -= level_height
|
||||
|
||||
stop_points_right = start_points.copy()
|
||||
stop_points_right[:,0] += 0.5 * unit_width
|
||||
stop_points_right[:,1] -= level_height
|
||||
|
||||
for (p,q) in zip(start_points,stop_points_left):
|
||||
alpha = np.abs((p[0]+q[0])/2) / half_width
|
||||
color = rainbow_color(alpha)
|
||||
line = Line(p,q, stroke_color = color)
|
||||
self.add(line)
|
||||
stop_points_right = start_points.copy()
|
||||
stop_points_right[:,0] += 0.5 * unit_width
|
||||
stop_points_right[:,1] -= level_height
|
||||
|
||||
for (p,q) in zip(start_points,stop_points_left):
|
||||
alpha = np.abs((p[0]+q[0])/2) / half_width
|
||||
color = rainbow_color(alpha)
|
||||
line = Line(p,q, stroke_color = color)
|
||||
self.add(line)
|
||||
|
||||
for (i,(p,q)) in enumerate(zip(start_points,stop_points_right)):
|
||||
alpha = np.abs((p[0]+q[0])/2) / half_width
|
||||
color = rainbow_color(alpha)
|
||||
line = Line(p,q, stroke_color = color)
|
||||
self.add(line)
|
||||
for (i,(p,q)) in enumerate(zip(start_points,stop_points_right)):
|
||||
alpha = np.abs((p[0]+q[0])/2) / half_width
|
||||
color = rainbow_color(alpha)
|
||||
line = Line(p,q, stroke_color = color)
|
||||
self.add(line)
|
||||
|
||||
if (n + 1) % dev_y_step == 0 and n != 1:
|
||||
j += dev_x_step
|
||||
dev_stop = stop_points_left[j]
|
||||
line = Line(dev_start,dev_stop,stroke_color = WHITE)
|
||||
self.add(line)
|
||||
dot = Dot(dev_stop, fill_color = WHITE)
|
||||
self.add_foreground_mobject(dot)
|
||||
dev_start = dev_stop
|
||||
if (n + 1) % dev_y_step == 0 and n != 1:
|
||||
j += dev_x_step
|
||||
dev_stop = stop_points_left[j]
|
||||
line = Line(dev_start,dev_stop,stroke_color = WHITE)
|
||||
self.add(line)
|
||||
dot = Dot(dev_stop, fill_color = WHITE)
|
||||
self.add_foreground_mobject(dot)
|
||||
dev_start = dev_stop
|
||||
|
||||
start_points = np.append(stop_points_left,[stop_points_right[-1]], axis = 0)
|
||||
start_points = np.append(stop_points_left,[stop_points_right[-1]], axis = 0)
|
||||
|
||||
|
||||
self.wait()
|
||||
self.wait()
|
||||
|
||||
|
||||
|
||||
class RescaledPascalNetScene(Scene):
|
||||
|
||||
def construct(self):
|
||||
def construct(self):
|
||||
|
||||
half_width = 3.0
|
||||
top_height = 4.0
|
||||
level_height = 2.0 * top_height / nb_levels
|
||||
half_width = 3.0
|
||||
top_height = 4.0
|
||||
level_height = 2.0 * top_height / nb_levels
|
||||
|
||||
start_points = np.array([top_height * UP])
|
||||
left_edge = top_height * UP + half_width * LEFT
|
||||
right_edge = top_height * UP + half_width * RIGHT
|
||||
start_points = np.array([top_height * UP])
|
||||
left_edge = top_height * UP + half_width * LEFT
|
||||
right_edge = top_height * UP + half_width * RIGHT
|
||||
|
||||
dev_start = start_points[0]
|
||||
dev_start = start_points[0]
|
||||
|
||||
j = 0
|
||||
j = 0
|
||||
|
||||
for n in range(nb_levels):
|
||||
for n in range(nb_levels):
|
||||
|
||||
if n == 0:
|
||||
start_points_left_shift = np.array([left_edge])
|
||||
else:
|
||||
start_points_left_shift = start_points[:-1]
|
||||
start_points_left_shift = np.insert(start_points_left_shift,0,left_edge, axis = 0)
|
||||
stop_points_left = 0.5 * (start_points + start_points_left_shift)
|
||||
stop_points_left += level_height * DOWN
|
||||
if n == 0:
|
||||
start_points_left_shift = np.array([left_edge])
|
||||
else:
|
||||
start_points_left_shift = start_points[:-1]
|
||||
start_points_left_shift = np.insert(start_points_left_shift,0,left_edge, axis = 0)
|
||||
stop_points_left = 0.5 * (start_points + start_points_left_shift)
|
||||
stop_points_left += level_height * DOWN
|
||||
|
||||
|
||||
if n == 0:
|
||||
start_points_right_shift = np.array([right_edge])
|
||||
else:
|
||||
start_points_right_shift = start_points[1:]
|
||||
start_points_right_shift = np.append(start_points_right_shift,np.array([right_edge]), axis = 0)
|
||||
stop_points_right = 0.5 * (start_points + start_points_right_shift)
|
||||
stop_points_right += level_height * DOWN
|
||||
|
||||
if n == 0:
|
||||
start_points_right_shift = np.array([right_edge])
|
||||
else:
|
||||
start_points_right_shift = start_points[1:]
|
||||
start_points_right_shift = np.append(start_points_right_shift,np.array([right_edge]), axis = 0)
|
||||
stop_points_right = 0.5 * (start_points + start_points_right_shift)
|
||||
stop_points_right += level_height * DOWN
|
||||
|
||||
|
||||
for (i,(p,q)) in enumerate(zip(start_points,stop_points_left)):
|
||||
|
||||
color = LIGHT_GRAY
|
||||
|
||||
for (i,(p,q)) in enumerate(zip(start_points,stop_points_left)):
|
||||
|
||||
color = LIGHT_GRAY
|
||||
|
||||
if n % 2 == 0 and i <= n/2:
|
||||
m = n/2 + 0.25
|
||||
jj = i
|
||||
alpha = 1 - float(jj)/m
|
||||
color = rainbow_color(alpha)
|
||||
if n % 2 == 0 and i <= n/2:
|
||||
m = n/2 + 0.25
|
||||
jj = i
|
||||
alpha = 1 - float(jj)/m
|
||||
color = rainbow_color(alpha)
|
||||
|
||||
elif n % 2 == 0 and i > n/2:
|
||||
m = n/2 + 0.25
|
||||
jj = n - i + 0.5
|
||||
alpha = 1 - float(jj)/m
|
||||
color = rainbow_color(alpha)
|
||||
elif n % 2 == 0 and i > n/2:
|
||||
m = n/2 + 0.25
|
||||
jj = n - i + 0.5
|
||||
alpha = 1 - float(jj)/m
|
||||
color = rainbow_color(alpha)
|
||||
|
||||
elif n % 2 == 1 and i <= n/2:
|
||||
m = n/2 + 0.75
|
||||
jj = i
|
||||
alpha = 1 - float(jj)/m
|
||||
color = rainbow_color(alpha)
|
||||
elif n % 2 == 1 and i <= n/2:
|
||||
m = n/2 + 0.75
|
||||
jj = i
|
||||
alpha = 1 - float(jj)/m
|
||||
color = rainbow_color(alpha)
|
||||
|
||||
elif n % 2 == 1 and i > n/2:
|
||||
m = n/2 + 0.75
|
||||
jj = n - i + 0.5
|
||||
alpha = 1 - float(jj)/m
|
||||
color = rainbow_color(alpha)
|
||||
elif n % 2 == 1 and i > n/2:
|
||||
m = n/2 + 0.75
|
||||
jj = n - i + 0.5
|
||||
alpha = 1 - float(jj)/m
|
||||
color = rainbow_color(alpha)
|
||||
|
||||
line = Line(p,q, stroke_color = color)
|
||||
self.add(line)
|
||||
line = Line(p,q, stroke_color = color)
|
||||
self.add(line)
|
||||
|
||||
for (i,(p,q)) in enumerate(zip(start_points,stop_points_right)):
|
||||
|
||||
color = LIGHT_GRAY
|
||||
for (i,(p,q)) in enumerate(zip(start_points,stop_points_right)):
|
||||
|
||||
color = LIGHT_GRAY
|
||||
|
||||
if n % 2 == 0 and i < n/2:
|
||||
m = n/2 + 0.25
|
||||
jj = i + 0.5
|
||||
alpha = 1 - float(jj)/m
|
||||
color = rainbow_color(alpha)
|
||||
if n % 2 == 0 and i < n/2:
|
||||
m = n/2 + 0.25
|
||||
jj = i + 0.5
|
||||
alpha = 1 - float(jj)/m
|
||||
color = rainbow_color(alpha)
|
||||
|
||||
elif n % 2 == 0 and i >= n/2:
|
||||
m = n/2 + 0.25
|
||||
jj = n - i
|
||||
alpha = 1 - float(jj)/m
|
||||
color = rainbow_color(alpha)
|
||||
elif n % 2 == 0 and i >= n/2:
|
||||
m = n/2 + 0.25
|
||||
jj = n - i
|
||||
alpha = 1 - float(jj)/m
|
||||
color = rainbow_color(alpha)
|
||||
|
||||
elif n % 2 == 1 and i <= n/2:
|
||||
m = n/2 + 0.75
|
||||
jj = i + 0.5
|
||||
alpha = 1 - float(jj)/m
|
||||
color = rainbow_color(alpha)
|
||||
elif n % 2 == 1 and i <= n/2:
|
||||
m = n/2 + 0.75
|
||||
jj = i + 0.5
|
||||
alpha = 1 - float(jj)/m
|
||||
color = rainbow_color(alpha)
|
||||
|
||||
elif n % 2 == 1 and i > n/2:
|
||||
m = n/2 + 0.75
|
||||
jj = n - i
|
||||
alpha = 1 - float(jj)/m
|
||||
color = rainbow_color(alpha)
|
||||
elif n % 2 == 1 and i > n/2:
|
||||
m = n/2 + 0.75
|
||||
jj = n - i
|
||||
alpha = 1 - float(jj)/m
|
||||
color = rainbow_color(alpha)
|
||||
|
||||
|
||||
line = Line(p,q, stroke_color = color)
|
||||
self.add(line)
|
||||
line = Line(p,q, stroke_color = color)
|
||||
self.add(line)
|
||||
|
||||
if (n + 1) % dev_y_step == 0 and n != 1:
|
||||
j += dev_x_step
|
||||
dev_stop = stop_points_left[j]
|
||||
line = Line(dev_start,dev_stop,stroke_color = WHITE)
|
||||
self.add(line)
|
||||
dot = Dot(dev_stop, fill_color = WHITE)
|
||||
self.add_foreground_mobject(dot)
|
||||
dev_start = dev_stop
|
||||
if (n + 1) % dev_y_step == 0 and n != 1:
|
||||
j += dev_x_step
|
||||
dev_stop = stop_points_left[j]
|
||||
line = Line(dev_start,dev_stop,stroke_color = WHITE)
|
||||
self.add(line)
|
||||
dot = Dot(dev_stop, fill_color = WHITE)
|
||||
self.add_foreground_mobject(dot)
|
||||
dev_start = dev_stop
|
||||
|
||||
|
||||
|
||||
start_points = np.append(stop_points_left,[stop_points_right[-1]], axis = 0)
|
||||
|
||||
left_edge += level_height * DOWN
|
||||
right_edge += level_height * DOWN
|
||||
start_points = np.append(stop_points_left,[stop_points_right[-1]], axis = 0)
|
||||
|
||||
left_edge += level_height * DOWN
|
||||
right_edge += level_height * DOWN
|
||||
|
||||
|
||||
self.wait()
|
||||
self.wait()
|
||||
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user