mirror of
https://github.com/3b1b/manim.git
synced 2025-07-30 13:34:19 +08:00
Switched to rgba standard. Quite possibly this will mess something up :)
This commit is contained in:
55
camera.py
55
camera.py
@ -20,6 +20,8 @@ class Camera(object):
|
|||||||
#Points in vectorized mobjects with norm greater
|
#Points in vectorized mobjects with norm greater
|
||||||
#than this value will be rescaled.
|
#than this value will be rescaled.
|
||||||
"max_allowable_norm" : 2*SPACE_WIDTH,
|
"max_allowable_norm" : 2*SPACE_WIDTH,
|
||||||
|
"image_mode" : "RGBA",
|
||||||
|
"n_rgb_coords" : 4,
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, background = None, **kwargs):
|
def __init__(self, background = None, **kwargs):
|
||||||
@ -46,18 +48,20 @@ class Camera(object):
|
|||||||
def init_background(self):
|
def init_background(self):
|
||||||
if self.background_image is not None:
|
if self.background_image is not None:
|
||||||
path = get_full_image_path(self.background_image)
|
path = get_full_image_path(self.background_image)
|
||||||
image = Image.open(path).convert('RGB')
|
image = Image.open(path).convert(self.image_mode)
|
||||||
height, width = self.pixel_shape
|
height, width = self.pixel_shape
|
||||||
#TODO, how to gracefully handle backgrounds
|
#TODO, how to gracefully handle backgrounds
|
||||||
#with different sizes?
|
#with different sizes?
|
||||||
self.background = np.array(image)[:height, :width]
|
self.background = np.array(image)[:height, :width]
|
||||||
else:
|
else:
|
||||||
background_rgb = color_to_int_rgb(self.background_color)
|
background_rgba = color_to_int_rgba(
|
||||||
|
self.background_color, alpha = 0
|
||||||
|
)
|
||||||
self.background = np.zeros(
|
self.background = np.zeros(
|
||||||
list(self.pixel_shape)+[3],
|
list(self.pixel_shape)+[self.n_rgb_coords],
|
||||||
dtype = 'uint8'
|
dtype = 'uint8'
|
||||||
)
|
)
|
||||||
self.background[:,:] = background_rgb
|
self.background[:,:] = background_rgba
|
||||||
|
|
||||||
def get_image(self):
|
def get_image(self):
|
||||||
return np.array(self.pixel_array)
|
return np.array(self.pixel_array)
|
||||||
@ -88,7 +92,7 @@ class Camera(object):
|
|||||||
self.display_multiple_vectorized_mobjects(vmobjects)
|
self.display_multiple_vectorized_mobjects(vmobjects)
|
||||||
vmobjects = []
|
vmobjects = []
|
||||||
self.display_point_cloud(
|
self.display_point_cloud(
|
||||||
mobject.points, mobject.rgbs,
|
mobject.points, mobject.rgbas,
|
||||||
self.adjusted_thickness(mobject.stroke_width)
|
self.adjusted_thickness(mobject.stroke_width)
|
||||||
)
|
)
|
||||||
elif isinstance(mobject, ImageMobject):
|
elif isinstance(mobject, ImageMobject):
|
||||||
@ -102,11 +106,12 @@ class Camera(object):
|
|||||||
if len(vmobjects) == 0:
|
if len(vmobjects) == 0:
|
||||||
return
|
return
|
||||||
#More efficient to bundle together in one "canvas"
|
#More efficient to bundle together in one "canvas"
|
||||||
image = Image.fromarray(self.pixel_array, mode = "RGB")
|
image = Image.fromarray(self.pixel_array, mode = self.image_mode)
|
||||||
canvas = aggdraw.Draw(image)
|
canvas = aggdraw.Draw(image)
|
||||||
for vmobject in vmobjects:
|
for vmobject in vmobjects:
|
||||||
self.display_vectorized(vmobject, canvas)
|
self.display_vectorized(vmobject, canvas)
|
||||||
canvas.flush()
|
canvas.flush()
|
||||||
|
|
||||||
self.pixel_array[:,:] = image
|
self.pixel_array[:,:] = image
|
||||||
|
|
||||||
def display_vectorized(self, vmobject, canvas):
|
def display_vectorized(self, vmobject, canvas):
|
||||||
@ -159,7 +164,7 @@ class Camera(object):
|
|||||||
result += " ".join([start] + cubics + [end])
|
result += " ".join([start] + cubics + [end])
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def display_point_cloud(self, points, rgbs, thickness):
|
def display_point_cloud(self, points, rgbas, thickness):
|
||||||
if len(points) == 0:
|
if len(points) == 0:
|
||||||
return
|
return
|
||||||
points = self.align_points_to_camera(points)
|
points = self.align_points_to_camera(points)
|
||||||
@ -167,15 +172,16 @@ class Camera(object):
|
|||||||
pixel_coords = self.thickened_coordinates(
|
pixel_coords = self.thickened_coordinates(
|
||||||
pixel_coords, thickness
|
pixel_coords, thickness
|
||||||
)
|
)
|
||||||
|
rgb_len = self.pixel_array.shape[2]
|
||||||
|
|
||||||
rgbs = (255*rgbs).astype('uint8')
|
rgbas = (255*rgbas).astype('uint8')
|
||||||
target_len = len(pixel_coords)
|
target_len = len(pixel_coords)
|
||||||
factor = target_len/len(rgbs)
|
factor = target_len/len(rgbas)
|
||||||
rgbs = np.array([rgbs]*factor).reshape((target_len, 3))
|
rgbas = np.array([rgbas]*factor).reshape((target_len, rgb_len))
|
||||||
|
|
||||||
on_screen_indices = self.on_screen_pixels(pixel_coords)
|
on_screen_indices = self.on_screen_pixels(pixel_coords)
|
||||||
pixel_coords = pixel_coords[on_screen_indices]
|
pixel_coords = pixel_coords[on_screen_indices]
|
||||||
rgbs = rgbs[on_screen_indices]
|
rgbas = rgbas[on_screen_indices]
|
||||||
|
|
||||||
ph, pw = self.pixel_shape
|
ph, pw = self.pixel_shape
|
||||||
|
|
||||||
@ -184,9 +190,9 @@ class Camera(object):
|
|||||||
indices = np.dot(pixel_coords, flattener)[:,0]
|
indices = np.dot(pixel_coords, flattener)[:,0]
|
||||||
indices = indices.astype('int')
|
indices = indices.astype('int')
|
||||||
|
|
||||||
new_pa = self.pixel_array.reshape((ph*pw, 3))
|
new_pa = self.pixel_array.reshape((ph*pw, rgb_len))
|
||||||
new_pa[indices] = rgbs
|
new_pa[indices] = rgbas
|
||||||
self.pixel_array = new_pa.reshape((ph, pw, 3))
|
self.pixel_array = new_pa.reshape((ph, pw, rgb_len))
|
||||||
|
|
||||||
def display_image_mobject(self, image_mobject):
|
def display_image_mobject(self, image_mobject):
|
||||||
corner_coords = self.points_to_pixel_coords(image_mobject.points)
|
corner_coords = self.points_to_pixel_coords(image_mobject.points)
|
||||||
@ -226,11 +232,26 @@ class Camera(object):
|
|||||||
n_to_change = np.sum(to_change)
|
n_to_change = np.sum(to_change)
|
||||||
inner_flat_coords = iw*iy_coords[to_change] + ix_coords[to_change]
|
inner_flat_coords = iw*iy_coords[to_change] + ix_coords[to_change]
|
||||||
flat_impa = impa.reshape((iw*ih, rgb_len))
|
flat_impa = impa.reshape((iw*ih, rgb_len))
|
||||||
target_rgbs = flat_impa[inner_flat_coords, :]
|
target_rgbas = flat_impa[inner_flat_coords, :]
|
||||||
|
|
||||||
flat_pa = self.pixel_array.reshape((ow*oh, rgb_len))
|
image = np.zeros((ow*oh, rgb_len), dtype = 'uint8')
|
||||||
flat_pa[to_change] = target_rgbs
|
image[to_change] = target_rgbas
|
||||||
|
image = image.reshape((oh, ow, rgb_len))
|
||||||
|
self.overlay_rgba_array(image)
|
||||||
|
|
||||||
|
def overlay_rgba_array(self, arr):
|
||||||
|
""" Overlays arr onto self.pixel_array with relevant alphas"""
|
||||||
|
bg, fg = self.pixel_array/255.0, arr/255.0
|
||||||
|
A = 1 - (1 - bg[:,:,3])*(1 - fg[:,:,3])
|
||||||
|
alpha_sum = bg[:,:,3] + fg[:,:,3]
|
||||||
|
for i in range(3):
|
||||||
|
with np.errstate(divide = 'ignore', invalid='ignore'):
|
||||||
|
bg[:,:,i] = reduce(op.add, [
|
||||||
|
np.divide(arr[:,:,i]*arr[:,:,3], alpha_sum)
|
||||||
|
for arr in fg, bg
|
||||||
|
])
|
||||||
|
bg[:,:,3] = A
|
||||||
|
self.pixel_array = (255*bg).astype('uint8')
|
||||||
|
|
||||||
def align_points_to_camera(self, points):
|
def align_points_to_camera(self, points):
|
||||||
## This is where projection should live
|
## This is where projection should live
|
||||||
|
13
helpers.py
13
helpers.py
@ -109,21 +109,32 @@ def diag_to_matrix(l_and_u, diag):
|
|||||||
def is_closed(points):
|
def is_closed(points):
|
||||||
return np.linalg.norm(points[0] - points[-1]) < CLOSED_THRESHOLD
|
return np.linalg.norm(points[0] - points[-1]) < CLOSED_THRESHOLD
|
||||||
|
|
||||||
|
## Color
|
||||||
|
|
||||||
def color_to_rgb(color):
|
def color_to_rgb(color):
|
||||||
return np.array(Color(color).get_rgb())
|
return np.array(Color(color).get_rgb())
|
||||||
|
|
||||||
|
def color_to_rgba(color, alpha = 1):
|
||||||
|
return np.append(color_to_rgb(color), [alpha])
|
||||||
|
|
||||||
def rgb_to_color(rgb):
|
def rgb_to_color(rgb):
|
||||||
try:
|
try:
|
||||||
return Color(rgb = rgb)
|
return Color(rgb = rgb)
|
||||||
except:
|
except:
|
||||||
return Color(WHITE)
|
return Color(WHITE)
|
||||||
|
|
||||||
|
def rgba_to_color(rgba):
|
||||||
|
return rgb_to_color(rgba[:3])
|
||||||
|
|
||||||
def invert_color(color):
|
def invert_color(color):
|
||||||
return rgb_to_color(1.0 - color_to_rgb(color))
|
return rgb_to_color(1.0 - color_to_rgb(color))
|
||||||
|
|
||||||
def color_to_int_rgb(color):
|
def color_to_int_rgb(color):
|
||||||
return (255*color_to_rgb(color)).astype('uint8')
|
return (255*color_to_rgb(color)).astype('uint8')
|
||||||
|
|
||||||
|
def color_to_int_rgba(color, alpha = 255):
|
||||||
|
return np.append(color_to_int_rgb(color), alpha)
|
||||||
|
|
||||||
def color_gradient(reference_colors, length_of_output):
|
def color_gradient(reference_colors, length_of_output):
|
||||||
if length_of_output == 0:
|
if length_of_output == 0:
|
||||||
return reference_colors[0]
|
return reference_colors[0]
|
||||||
@ -148,6 +159,8 @@ def average_color(*colors):
|
|||||||
mean_rgb = np.apply_along_axis(np.mean, 0, rgbs)
|
mean_rgb = np.apply_along_axis(np.mean, 0, rgbs)
|
||||||
return rgb_to_color(mean_rgb)
|
return rgb_to_color(mean_rgb)
|
||||||
|
|
||||||
|
###
|
||||||
|
|
||||||
def compass_directions(n = 4, start_vect = RIGHT):
|
def compass_directions(n = 4, start_vect = RIGHT):
|
||||||
angle = 2*np.pi/n
|
angle = 2*np.pi/n
|
||||||
return np.array([
|
return np.array([
|
||||||
|
@ -17,11 +17,13 @@ class ImageMobject(Mobject):
|
|||||||
"invert" : False,
|
"invert" : False,
|
||||||
# "use_cache" : True,
|
# "use_cache" : True,
|
||||||
"height": 2.0,
|
"height": 2.0,
|
||||||
|
"image_mode" : "RGBA"
|
||||||
}
|
}
|
||||||
def __init__(self, filename_or_array, **kwargs):
|
def __init__(self, filename_or_array, **kwargs):
|
||||||
|
digest_config(self, kwargs)
|
||||||
if isinstance(filename_or_array, str):
|
if isinstance(filename_or_array, str):
|
||||||
path = get_full_image_path(filename_or_array)
|
path = get_full_image_path(filename_or_array)
|
||||||
image = Image.open(path).convert("RGB")
|
image = Image.open(path).convert(self.image_mode)
|
||||||
self.pixel_array = np.array(image)
|
self.pixel_array = np.array(image)
|
||||||
else:
|
else:
|
||||||
self.pixel_array = np.array(filename_or_array)
|
self.pixel_array = np.array(filename_or_array)
|
||||||
@ -41,9 +43,13 @@ class ImageMobject(Mobject):
|
|||||||
h, w = self.pixel_array.shape[:2]
|
h, w = self.pixel_array.shape[:2]
|
||||||
self.stretch_to_fit_width(self.height*w/h)
|
self.stretch_to_fit_width(self.height*w/h)
|
||||||
|
|
||||||
|
def set_opacity(self, alpha):
|
||||||
|
self.pixel_array[:,:,3] = int(255*alpha)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def fade(self, darkness = 0.5):
|
||||||
|
self.set_opacity(1 - darkness)
|
||||||
|
return self
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -3,49 +3,50 @@ from helpers import *
|
|||||||
|
|
||||||
class PMobject(Mobject):
|
class PMobject(Mobject):
|
||||||
def init_points(self):
|
def init_points(self):
|
||||||
self.rgbs = np.zeros((0, 3))
|
self.rgbas = np.zeros((0, 4))
|
||||||
self.points = np.zeros((0, 3))
|
self.points = np.zeros((0, 3))
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def get_array_attrs(self):
|
def get_array_attrs(self):
|
||||||
return Mobject.get_array_attrs(self) + ["rgbs"]
|
return Mobject.get_array_attrs(self) + ["rgbas"]
|
||||||
|
|
||||||
def add_points(self, points, rgbs = None, color = None):
|
def add_points(self, points, rgbas = None, color = None, alpha = 1):
|
||||||
"""
|
"""
|
||||||
points must be a Nx3 numpy array, as must rgbs if it is not None
|
points must be a Nx3 numpy array, as must rgbas if it is not None
|
||||||
"""
|
"""
|
||||||
if not isinstance(points, np.ndarray):
|
if not isinstance(points, np.ndarray):
|
||||||
points = np.array(points)
|
points = np.array(points)
|
||||||
num_new_points = points.shape[0]
|
num_new_points = len(points)
|
||||||
self.points = np.append(self.points, points, axis = 0)
|
self.points = np.append(self.points, points, axis = 0)
|
||||||
if rgbs is None:
|
if rgbas is None:
|
||||||
color = Color(color) if color else self.color
|
color = Color(color) if color else self.color
|
||||||
rgbs = np.array([color.get_rgb()] * num_new_points)
|
rgbas = np.repeat(
|
||||||
elif rgbs.shape != points.shape:
|
[color_to_rgba(color, alpha)],
|
||||||
raise Exception("points and rgbs must have same shape")
|
num_new_points,
|
||||||
self.rgbs = np.append(self.rgbs, rgbs, axis = 0)
|
axis = 0
|
||||||
|
)
|
||||||
|
elif len(rgbas) != len(points):
|
||||||
|
raise Exception("points and rgbas must have same shape")
|
||||||
|
self.rgbas = np.append(self.rgbas, rgbas, axis = 0)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def highlight(self, color = YELLOW_C, family = True, condition = None):
|
def highlight(self, color = YELLOW_C, family = True, condition = None):
|
||||||
rgb = Color(color).get_rgb()
|
rgba = color_to_rgba(color)
|
||||||
mobs = self.family_members_with_points() if family else [self]
|
mobs = self.family_members_with_points() if family else [self]
|
||||||
for mob in mobs:
|
for mob in mobs:
|
||||||
if condition:
|
if condition:
|
||||||
to_change = np.apply_along_axis(condition, 1, mob.points)
|
to_change = np.apply_along_axis(condition, 1, mob.points)
|
||||||
mob.rgbs[to_change, :] = rgb
|
mob.rgbas[to_change, :] = rgba
|
||||||
else:
|
else:
|
||||||
mob.rgbs[:,:] = rgb
|
mob.rgbas[:,:] = rgba
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def gradient_highlight(self, start_color, end_color):
|
def gradient_highlight(self, start_color, end_color):
|
||||||
start_rgb, end_rgb = [
|
start_rgba, end_rgba = map(color_to_rgba, [start_color, end_color])
|
||||||
np.array(Color(color).get_rgb())
|
|
||||||
for color in start_color, end_color
|
|
||||||
]
|
|
||||||
for mob in self.family_members_with_points():
|
for mob in self.family_members_with_points():
|
||||||
num_points = mob.get_num_points()
|
num_points = mob.get_num_points()
|
||||||
mob.rgbs = np.array([
|
mob.rgbas = np.array([
|
||||||
interpolate(start_rgb, end_rgb, alpha)
|
interpolate(start_rgba, end_rgba, alpha)
|
||||||
for alpha in np.arange(num_points)/float(num_points)
|
for alpha in np.arange(num_points)/float(num_points)
|
||||||
])
|
])
|
||||||
return self
|
return self
|
||||||
@ -53,14 +54,14 @@ class PMobject(Mobject):
|
|||||||
|
|
||||||
def match_colors(self, mobject):
|
def match_colors(self, mobject):
|
||||||
Mobject.align_data(self, mobject)
|
Mobject.align_data(self, mobject)
|
||||||
self.rgbs = np.array(mobject.rgbs)
|
self.rgbas = np.array(mobject.rgbas)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def filter_out(self, condition):
|
def filter_out(self, condition):
|
||||||
for mob in self.family_members_with_points():
|
for mob in self.family_members_with_points():
|
||||||
to_eliminate = ~np.apply_along_axis(condition, 1, mob.points)
|
to_eliminate = ~np.apply_along_axis(condition, 1, mob.points)
|
||||||
mob.points = mob.points[to_eliminate]
|
mob.points = mob.points[to_eliminate]
|
||||||
mob.rgbs = mob.rgbs[to_eliminate]
|
mob.rgbas = mob.rgbas[to_eliminate]
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def thin_out(self, factor = 5):
|
def thin_out(self, factor = 5):
|
||||||
@ -88,13 +89,13 @@ class PMobject(Mobject):
|
|||||||
return self
|
return self
|
||||||
|
|
||||||
def fade_to(self, color, alpha):
|
def fade_to(self, color, alpha):
|
||||||
self.rgbs = interpolate(self.rgbs, np.array(Color(color).rgb), alpha)
|
self.rgbas = interpolate(self.rgbas, color_to_rgba(color), alpha)
|
||||||
for mob in self.submobjects:
|
for mob in self.submobjects:
|
||||||
mob.fade_to(color, alpha)
|
mob.fade_to(color, alpha)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def get_all_rgbs(self):
|
def get_all_rgbas(self):
|
||||||
return self.get_merged_array("rgbs")
|
return self.get_merged_array("rgbas")
|
||||||
|
|
||||||
def ingest_submobjects(self):
|
def ingest_submobjects(self):
|
||||||
attrs = self.get_array_attrs()
|
attrs = self.get_array_attrs()
|
||||||
@ -105,7 +106,7 @@ class PMobject(Mobject):
|
|||||||
return self
|
return self
|
||||||
|
|
||||||
def get_color(self):
|
def get_color(self):
|
||||||
return Color(rgb = self.rgbs[0, :])
|
return rgba_to_color(self.rgbas[0, :])
|
||||||
|
|
||||||
def point_from_proportion(self, alpha):
|
def point_from_proportion(self, alpha):
|
||||||
index = alpha*(self.get_num_points()-1)
|
index = alpha*(self.get_num_points()-1)
|
||||||
@ -126,8 +127,8 @@ class PMobject(Mobject):
|
|||||||
return Point(center)
|
return Point(center)
|
||||||
|
|
||||||
def interpolate_color(self, mobject1, mobject2, alpha):
|
def interpolate_color(self, mobject1, mobject2, alpha):
|
||||||
self.rgbs = interpolate(
|
self.rgbas = interpolate(
|
||||||
mobject1.rgbs, mobject2.rgbs, alpha
|
mobject1.rgbas, mobject2.rgbas, alpha
|
||||||
)
|
)
|
||||||
|
|
||||||
def pointwise_become_partial(self, mobject, a, b):
|
def pointwise_become_partial(self, mobject, a, b):
|
||||||
|
@ -318,8 +318,8 @@ class MoreFiltersMoreLight(FilterScene):
|
|||||||
phi, theta = self.camera.get_phi(), self.camera.get_theta()
|
phi, theta = self.camera.get_phi(), self.camera.get_theta()
|
||||||
self.set_camera_position(np.pi/2, -np.pi)
|
self.set_camera_position(np.pi/2, -np.pi)
|
||||||
|
|
||||||
self.original_rgbs = [(255, 255, 255)]
|
self.original_rgbas = [(255, 255, 255)]
|
||||||
self.new_rgbs = [self.arrow_rgb]
|
self.new_rgbas = [self.arrow_rgb]
|
||||||
for bool_array in it.product(*5*[[True, False]]):
|
for bool_array in it.product(*5*[[True, False]]):
|
||||||
pfs_to_use = VGroup(*[
|
pfs_to_use = VGroup(*[
|
||||||
pf
|
pf
|
||||||
@ -330,7 +330,7 @@ class MoreFiltersMoreLight(FilterScene):
|
|||||||
frame = self.camera.get_image()
|
frame = self.camera.get_image()
|
||||||
h, w, three = frame.shape
|
h, w, three = frame.shape
|
||||||
rgb = frame[3*h/8, 7*w/12]
|
rgb = frame[3*h/8, 7*w/12]
|
||||||
self.original_rgbs.append(rgb)
|
self.original_rgbas.append(rgb)
|
||||||
|
|
||||||
angles = [pf.filter_angle for pf in pfs_to_use]
|
angles = [pf.filter_angle for pf in pfs_to_use]
|
||||||
p = 0.5
|
p = 0.5
|
||||||
@ -340,7 +340,7 @@ class MoreFiltersMoreLight(FilterScene):
|
|||||||
if not any(bool_array):
|
if not any(bool_array):
|
||||||
new_rgb = self.background_rgb
|
new_rgb = self.background_rgb
|
||||||
|
|
||||||
self.new_rgbs.append(new_rgb)
|
self.new_rgbas.append(new_rgb)
|
||||||
self.camera.reset()
|
self.camera.reset()
|
||||||
self.set_camera_position(phi, theta)
|
self.set_camera_position(phi, theta)
|
||||||
|
|
||||||
@ -351,9 +351,9 @@ class MoreFiltersMoreLight(FilterScene):
|
|||||||
frame = FilterScene.get_frame(self)
|
frame = FilterScene.get_frame(self)
|
||||||
bool_arrays = [
|
bool_arrays = [
|
||||||
(frame[:,:,0] == r) & (frame[:,:,1] == g) & (frame[:,:,2] == b)
|
(frame[:,:,0] == r) & (frame[:,:,1] == g) & (frame[:,:,2] == b)
|
||||||
for (r, g, b) in self.original_rgbs
|
for (r, g, b) in self.original_rgbas
|
||||||
]
|
]
|
||||||
for ba, new_rgb in zip(bool_arrays, self.new_rgbs):
|
for ba, new_rgb in zip(bool_arrays, self.new_rgbas):
|
||||||
frame[ba] = new_rgb
|
frame[ba] = new_rgb
|
||||||
covered = reduce(
|
covered = reduce(
|
||||||
lambda b1, b2 : b1 | b2,
|
lambda b1, b2 : b1 | b2,
|
||||||
|
@ -92,7 +92,7 @@ class SlideWordDownCycloid(Animation):
|
|||||||
time = min(time, 1)
|
time = min(time, 1)
|
||||||
if time < cut_offs[0]:
|
if time < cut_offs[0]:
|
||||||
brightness = time/cut_offs[0]
|
brightness = time/cut_offs[0]
|
||||||
letter.rgbs = brightness*np.ones(letter.rgbs.shape)
|
letter.rgbas = brightness*np.ones(letter.rgbas.shape)
|
||||||
position = self.path.points[0]
|
position = self.path.points[0]
|
||||||
angle = 0
|
angle = 0
|
||||||
elif time < cut_offs[1]:
|
elif time < cut_offs[1]:
|
||||||
|
@ -63,9 +63,9 @@ def sort_by_color(mob):
|
|||||||
indices = np.argsort(np.apply_along_axis(
|
indices = np.argsort(np.apply_along_axis(
|
||||||
lambda p : -np.linalg.norm(p),
|
lambda p : -np.linalg.norm(p),
|
||||||
1,
|
1,
|
||||||
mob.rgbs
|
mob.rgbas
|
||||||
))
|
))
|
||||||
mob.rgbs = mob.rgbs[indices]
|
mob.rgbas = mob.rgbas[indices]
|
||||||
mob.points = mob.points[indices]
|
mob.points = mob.points[indices]
|
||||||
|
|
||||||
|
|
||||||
@ -108,7 +108,7 @@ def nearest_neighbor_align(mobject1, mobject2):
|
|||||||
)
|
)
|
||||||
new_mob2.add_points(
|
new_mob2.add_points(
|
||||||
mobject2.points[indices],
|
mobject2.points[indices],
|
||||||
rgbs = mobject2.rgbs[indices]
|
rgbas = mobject2.rgbas[indices]
|
||||||
)
|
)
|
||||||
return new_mob1, new_mob2
|
return new_mob1, new_mob2
|
||||||
|
|
||||||
|
@ -334,7 +334,7 @@ class ShowLightAndSlidingObject(MultilayeredScene, TryManyPaths, PhotonScene):
|
|||||||
if path.get_height() > self.total_glass_height:
|
if path.get_height() > self.total_glass_height:
|
||||||
path.stretch(0.7, 1)
|
path.stretch(0.7, 1)
|
||||||
path.shift(self.top - path.get_top())
|
path.shift(self.top - path.get_top())
|
||||||
path.rgbs[:,2] = 0
|
path.rgbas[:,2] = 0
|
||||||
loop = paths.pop(1) ##Bad!
|
loop = paths.pop(1) ##Bad!
|
||||||
randy = Randolph()
|
randy = Randolph()
|
||||||
randy.scale(RANDY_SCALE_FACTOR)
|
randy.scale(RANDY_SCALE_FACTOR)
|
||||||
|
@ -330,7 +330,7 @@ class FermatsPrincipleStatement(Scene):
|
|||||||
norms -= np.min(norms)
|
norms -= np.min(norms)
|
||||||
norms /= np.max(norms)
|
norms /= np.max(norms)
|
||||||
alphas = 0.25 + 0.75 * norms * (1 + np.sin(12*angles))/2
|
alphas = 0.25 + 0.75 * norms * (1 + np.sin(12*angles))/2
|
||||||
everything.rgbs = alphas.repeat(3).reshape((len(alphas), 3))
|
everything.rgbas = alphas.repeat(3).reshape((len(alphas), 3))
|
||||||
|
|
||||||
Mobject(everything, words).show()
|
Mobject(everything, words).show()
|
||||||
|
|
||||||
|
@ -80,10 +80,10 @@ class HilbertCurveIsPerfect(Scene):
|
|||||||
closest_point_indices = np.apply_along_axis(
|
closest_point_indices = np.apply_along_axis(
|
||||||
np.argmin, 1, distance_matrix
|
np.argmin, 1, distance_matrix
|
||||||
)
|
)
|
||||||
colored_curve.rgbs = sparce_lion.rgbs[closest_point_indices]
|
colored_curve.rgbas = sparce_lion.rgbas[closest_point_indices]
|
||||||
line = Line(5*LEFT, 5*RIGHT)
|
line = Line(5*LEFT, 5*RIGHT)
|
||||||
Mobject.align_data(line, colored_curve)
|
Mobject.align_data(line, colored_curve)
|
||||||
line.rgbs = colored_curve.rgbs
|
line.rgbas = colored_curve.rgbas
|
||||||
|
|
||||||
self.add(lion)
|
self.add(lion)
|
||||||
self.play(ShowCreation(curve, run_time = 3))
|
self.play(ShowCreation(curve, run_time = 3))
|
||||||
@ -332,7 +332,7 @@ class PseudoHilbertCurvesDontFillSpace(Scene):
|
|||||||
square.digest_mobject_attrs()
|
square.digest_mobject_attrs()
|
||||||
square.scale(2**(-5))
|
square.scale(2**(-5))
|
||||||
square.corner.highlight(
|
square.corner.highlight(
|
||||||
Color(rgb = curve.rgbs[curve.get_num_points()/3])
|
Color(rgb = curve.rgbas[curve.get_num_points()/3])
|
||||||
)
|
)
|
||||||
square.shift(
|
square.shift(
|
||||||
grid.get_corner(UP+LEFT)-\
|
grid.get_corner(UP+LEFT)-\
|
||||||
|
@ -474,12 +474,12 @@ class TauPoem(Scene):
|
|||||||
)
|
)
|
||||||
blue_rgb = np.array(Color("blue").get_rgb())
|
blue_rgb = np.array(Color("blue").get_rgb())
|
||||||
white_rgb = np.ones(3)
|
white_rgb = np.ones(3)
|
||||||
circle.rgbs = np.array([
|
circle.rgbas = np.array([
|
||||||
alpha * blue_rgb + (1 - alpha) * white_rgb
|
alpha * blue_rgb + (1 - alpha) * white_rgb
|
||||||
for alpha in np.arange(0, 1, 1.0/len(circle.rgbs))
|
for alpha in np.arange(0, 1, 1.0/len(circle.rgbas))
|
||||||
])
|
])
|
||||||
for index in range(circle.points.shape[0]):
|
for index in range(circle.points.shape[0]):
|
||||||
circle.rgbs
|
circle.rgbas
|
||||||
def trianglify((x, y, z)):
|
def trianglify((x, y, z)):
|
||||||
norm = np.linalg.norm((x, y, z))
|
norm = np.linalg.norm((x, y, z))
|
||||||
comp = complex(x, y)*complex(0, 1)
|
comp = complex(x, y)*complex(0, 1)
|
||||||
|
@ -477,7 +477,7 @@ class Scene(object):
|
|||||||
'-f', 'rawvideo',
|
'-f', 'rawvideo',
|
||||||
'-vcodec','rawvideo',
|
'-vcodec','rawvideo',
|
||||||
'-s', '%dx%d'%(width, height), # size of one frame
|
'-s', '%dx%d'%(width, height), # size of one frame
|
||||||
'-pix_fmt', 'rgb24',
|
'-pix_fmt', 'rgba',
|
||||||
'-r', str(fps), # frames per second
|
'-r', str(fps), # frames per second
|
||||||
'-i', '-', # The imput comes from a pipe
|
'-i', '-', # The imput comes from a pipe
|
||||||
'-an', # Tells FFMPEG not to expect any audio
|
'-an', # Tells FFMPEG not to expect any audio
|
||||||
|
Reference in New Issue
Block a user