Refactor many definitions out of topics and into folders within mobject

This commit is contained in:
Grant Sanderson
2018-03-31 18:05:02 -07:00
parent accef01040
commit fc3dc64805
42 changed files with 547 additions and 464 deletions

View File

@ -5,9 +5,9 @@ import numpy as np
from constants import *
from animation.animation import Animation
from mobject.tex_mobject import TextMobject
from mobject.vectorized_mobject import VMobject
from mobject.vectorized_mobject import VectorizedPoint
from mobject.svg.tex_mobject import TextMobject
from mobject.types.vectorized_mobject import VMobject
from mobject.types.vectorized_mobject import VectorizedPoint
from animation.transform import Transform
from utils.bezier import interpolate
from utils.config_ops import digest_config

View File

@ -10,9 +10,9 @@ from animation.creation import ShowPartial
from animation.transform import Transform
from mobject.mobject import Group
from mobject.mobject import Mobject
from mobject.vectorized_mobject import VMobject
from topics.geometry import Circle
from topics.geometry import Dot
from mobject.types.vectorized_mobject import VMobject
from mobject.geometry import Circle
from mobject.geometry import Dot
from utils.config_ops import digest_config
from utils.rate_functions import squish_rate_func
from utils.rate_functions import there_and_back

67
animation/specialized.py Normal file
View File

@ -0,0 +1,67 @@
from __future__ import absolute_import
import numpy as np
from constants import *
from animation.transform import ApplyMethod
from animation.composition import LaggedStart
from mobject.svg.drawings import Car
from mobject.types.vectorized_mobject import VGroup
from mobject.geometry import Circle
from utils.config_ops import digest_config
class MoveCar(ApplyMethod):
CONFIG = {
"moving_forward" : True,
}
def __init__(self, car, target_point, **kwargs):
assert isinstance(car, Car)
ApplyMethod.__init__(self, car.move_to, target_point, **kwargs)
displacement = self.target_mobject.get_right()-self.starting_mobject.get_right()
distance = np.linalg.norm(displacement)
if not self.moving_forward:
distance *= -1
tire_radius = car.get_tires()[0].get_width()/2
self.total_tire_radians = -distance/tire_radius
def update_mobject(self, alpha):
ApplyMethod.update_mobject(self, alpha)
if alpha == 0:
return
radians = alpha*self.total_tire_radians
for tire in self.mobject.get_tires():
tire.rotate_in_place(radians)
class Broadcast(LaggedStart):
CONFIG = {
"small_radius" : 0.0,
"big_radius" : 5,
"n_circles" : 5,
"start_stroke_width" : 8,
"color" : WHITE,
"remover" : True,
"lag_ratio" : 0.7,
"run_time" : 3,
"remover" : True,
}
def __init__(self, focal_point, **kwargs):
digest_config(self, kwargs)
circles = VGroup()
for x in range(self.n_circles):
circle = Circle(
radius = self.big_radius,
stroke_color = BLACK,
stroke_width = 0,
)
circle.move_to(focal_point)
circle.save_state()
circle.scale_to_fit_width(self.small_radius*2)
circle.set_stroke(self.color, self.start_stroke_width)
circles.add(circle)
LaggedStart.__init__(
self, ApplyMethod, circles,
lambda c : (c.restore,),
**kwargs
)

View File

@ -21,6 +21,7 @@ from animation.creation import *
from animation.indication import *
from animation.movement import *
from animation.rotation import *
from animation.specialized import *
from animation.transform import *
from animation.update import *
@ -32,12 +33,17 @@ from continual_animation.continual_animation import *
from continual_animation.from_animation import *
from continual_animation.update import *
from mobject.image_mobject import *
from mobject.mobject import *
from mobject.point_cloud_mobject import *
from mobject.svg_mobject import *
from mobject.tex_mobject import *
from mobject.vectorized_mobject import *
from mobject.frame import *
from mobject.geometry import *
from mobject.shape_matchers import *
from mobject.value_tracker import *
from mobject.svg.brace import *
from mobject.svg.svg_mobject import *
from mobject.svg.tex_mobject import *
from mobject.types.image_mobject import *
from mobject.types.point_cloud_mobject import *
from mobject.types.vectorized_mobject import *
from pi_creature.pi_creature import *
from pi_creature.pi_creature_animations import *
@ -59,12 +65,10 @@ from once_useful_constructs.light import *
from topics.common_scenes import *
from topics.complex_numbers import *
from topics.functions import *
from topics.geometry import *
from topics.graph_scene import *
from topics.matrix import *
from topics.number_line import *
from topics.numerals import *
from topics.objects import *
from topics.probability import *
from topics.three_dimensions import *
from topics.vector_space_scene import *

View File

@ -10,10 +10,10 @@ from PIL import Image
from colour import Color
from constants import *
from mobject.image_mobject import ImageMobject
from mobject.types.image_mobject import ImageMobject
from mobject.mobject import Mobject
from mobject.point_cloud_mobject import PMobject
from mobject.vectorized_mobject import VMobject
from mobject.types.point_cloud_mobject import PMobject
from mobject.types.vectorized_mobject import VMobject
from utils.color import color_to_int_rgba
from utils.color import rgb_to_hex
from utils.config_ops import digest_config

44
mobject/frame.py Normal file
View File

@ -0,0 +1,44 @@
from __future__ import absolute_import
from constants import *
from mobject.geometry import Rectangle
from utils.config_ops import digest_config
class ScreenRectangle(Rectangle):
CONFIG = {
"width_to_height_ratio" : 16.0/9.0,
"height" : 4,
}
def generate_points(self):
self.width = self.width_to_height_ratio * self.height
Rectangle.generate_points(self)
class FullScreenRectangle(ScreenRectangle):
CONFIG = {
"height" : FRAME_HEIGHT,
}
class FullScreenFadeRectangle(FullScreenRectangle):
CONFIG = {
"stroke_width" : 0,
"fill_color" : BLACK,
"fill_opacity" : 0.7,
}
class PictureInPictureFrame(Rectangle):
CONFIG = {
"height" : 3,
"aspect_ratio" : (16, 9)
}
def __init__(self, **kwargs):
digest_config(self, kwargs)
height = self.height
if "height" in kwargs:
kwargs.pop("height")
Rectangle.__init__(
self,
width = self.aspect_ratio[0],
height = self.aspect_ratio[1],
**kwargs
)
self.scale_to_fit_height(height)

View File

@ -1,11 +1,13 @@
from __future__ import absolute_import
from constants import *
import itertools as it
import numpy as np
from mobject.mobject import Mobject
from mobject.vectorized_mobject import VGroup
from mobject.vectorized_mobject import VMobject
from mobject.types.vectorized_mobject import VGroup
from mobject.types.vectorized_mobject import VMobject
from utils.bezier import interpolate
from utils.config_ops import digest_config
from utils.config_ops import digest_locals
@ -495,18 +497,20 @@ class Arrow(Line):
stroke_color = self.color,
stroke_width = 0,
)
tip.add_at_end = add_at_end
self.set_tip_points(tip, add_at_end, preserve_normal = False)
self.add(tip)
if not hasattr(self, 'tip'):
self.tip = []
self.tip.append(tuple((tip, add_at_end)))
self.tip = VGroup()
self.tip.match_style(tip)
self.tip.add(tip)
return tip
def add_rectangular_stem(self):
self.rect = Rectangle(
stroke_width = 0,
fill_color = self.tip[0][0].get_fill_color(),
fill_opacity = self.tip[0][0].get_fill_opacity()
fill_color = self.tip.get_fill_color(),
fill_opacity = self.tip.get_fill_opacity()
)
self.add_to_back(self.rect)
self.set_stroke(width = 0)
@ -515,7 +519,7 @@ class Arrow(Line):
def set_rectangular_stem_points(self):
start, end = self.get_start_and_end()
vect = end - start
tip_base_points = self.tip[0][0].get_anchors()[1:]
tip_base_points = self.tip[0].get_anchors()[1:]
tip_base = center_of_mass(tip_base_points)
tbp1, tbp2 = tip_base_points
perp_vect = tbp2 - tbp1
@ -576,7 +580,7 @@ class Arrow(Line):
return self
def get_normal_vector(self):
p0, p1, p2 = self.tip[0][0].get_anchors()
p0, p1, p2 = self.tip[0].get_anchors()
result = np.cross(p2 - p1, p1 - p0)
norm = np.linalg.norm(result)
if norm == 0:
@ -590,7 +594,7 @@ class Arrow(Line):
def get_end(self):
if hasattr(self, "tip"):
return self.tip[0][0].get_anchors()[0]
return self.tip[0].get_anchors()[0]
else:
return Line.get_end(self)
@ -599,7 +603,7 @@ class Arrow(Line):
def put_start_and_end_on(self, *args, **kwargs):
Line.put_start_and_end_on(self, *args, **kwargs)
self.set_tip_points(self.tip[0][0], preserve_normal = False)
self.set_tip_points(self.tip[0], preserve_normal = False)
self.set_rectangular_stem_points()
return self
@ -607,8 +611,7 @@ class Arrow(Line):
Line.scale(self, scale_factor, **kwargs)
if self.preserve_tip_size_when_scaling:
for t in self.tip:
print(t)
self.set_tip_points(t[0], add_at_end=t[1])
self.set_tip_points(t, add_at_end=t.add_at_end)
if self.use_rectangular_stem:
self.set_rectangular_stem_points()
return self
@ -692,88 +695,6 @@ class Square(Rectangle):
**kwargs
)
class SurroundingRectangle(Rectangle):
CONFIG = {
"color" : YELLOW,
"buff" : SMALL_BUFF,
}
def __init__(self, mobject, **kwargs):
digest_config(self, kwargs)
kwargs["width"] = mobject.get_width() + 2*self.buff
kwargs["height"] = mobject.get_height() + 2*self.buff
Rectangle.__init__(self, **kwargs)
self.move_to(mobject)
class BackgroundRectangle(SurroundingRectangle):
CONFIG = {
"color" : BLACK,
"stroke_width" : 0,
"fill_opacity" : 0.75,
"buff" : 0
}
def __init__(self, mobject, **kwargs):
SurroundingRectangle.__init__(self, mobject, **kwargs)
self.original_fill_opacity = self.fill_opacity
def pointwise_become_partial(self, mobject, a, b):
self.set_fill(opacity = b*self.original_fill_opacity)
return self
def get_fill_color(self):
return Color(self.color)
class ScreenRectangle(Rectangle):
CONFIG = {
"width_to_height_ratio" : 16.0/9.0,
"height" : 4,
}
def generate_points(self):
self.width = self.width_to_height_ratio * self.height
Rectangle.generate_points(self)
class FullScreenRectangle(ScreenRectangle):
CONFIG = {
"height" : FRAME_HEIGHT,
}
class FullScreenFadeRectangle(FullScreenRectangle):
CONFIG = {
"stroke_width" : 0,
"fill_color" : BLACK,
"fill_opacity" : 0.7,
}
class PictureInPictureFrame(Rectangle):
CONFIG = {
"height" : 3,
"aspect_ratio" : (16, 9)
}
def __init__(self, **kwargs):
digest_config(self, kwargs)
height = self.height
if "height" in kwargs:
kwargs.pop("height")
Rectangle.__init__(
self,
width = self.aspect_ratio[0],
height = self.aspect_ratio[1],
**kwargs
)
self.scale_to_fit_height(height)
class Cross(VGroup):
CONFIG = {
"stroke_color" : RED,
"stroke_width" : 6,
}
def __init__(self, mobject, **kwargs):
VGroup.__init__(self,
Line(UP+LEFT, DOWN+RIGHT),
Line(UP+RIGHT, DOWN+LEFT),
)
self.replace(mobject, stretch = True)
self.set_stroke(self.stroke_color, self.stroke_width)
class Grid(VMobject):
CONFIG = {
"height" : 6.0,

56
mobject/shape_matchers.py Normal file
View File

@ -0,0 +1,56 @@
from __future__ import absolute_import
from constants import *
from mobject.geometry import Rectangle
from mobject.geometry import Line
from mobject.types.vectorized_mobject import VGroup
from utils.config_ops import digest_config
from utils.color import Color
class SurroundingRectangle(Rectangle):
CONFIG = {
"color" : YELLOW,
"buff" : SMALL_BUFF,
}
def __init__(self, mobject, **kwargs):
digest_config(self, kwargs)
kwargs["width"] = mobject.get_width() + 2*self.buff
kwargs["height"] = mobject.get_height() + 2*self.buff
Rectangle.__init__(self, **kwargs)
self.move_to(mobject)
class BackgroundRectangle(SurroundingRectangle):
CONFIG = {
"color" : BLACK,
"stroke_width" : 0,
"fill_opacity" : 0.75,
"buff" : 0
}
def __init__(self, mobject, **kwargs):
SurroundingRectangle.__init__(self, mobject, **kwargs)
self.original_fill_opacity = self.fill_opacity
def pointwise_become_partial(self, mobject, a, b):
self.set_fill(opacity = b*self.original_fill_opacity)
return self
def set_color(self):
# Can't be changin' me!
return self
def get_fill_color(self):
return Color(self.color)
class Cross(VGroup):
CONFIG = {
"stroke_color" : RED,
"stroke_width" : 6,
}
def __init__(self, mobject, **kwargs):
VGroup.__init__(self,
Line(UP+LEFT, DOWN+RIGHT),
Line(UP+RIGHT, DOWN+LEFT),
)
self.replace(mobject, stretch = True)
self.set_stroke(self.stroke_color, self.stroke_width)

0
mobject/svg/__init__.py Normal file
View File

130
mobject/svg/brace.py Normal file
View File

@ -0,0 +1,130 @@
from __future__ import absolute_import
import numpy as np
from constants import *
from animation.composition import AnimationGroup
from animation.creation import FadeIn
from animation.creation import GrowFromCenter
from mobject.svg.tex_mobject import TexMobject
from mobject.svg.tex_mobject import TextMobject
from mobject.types.vectorized_mobject import VMobject
from utils.config_ops import digest_config
class Brace(TexMobject):
CONFIG = {
"buff" : 0.2,
"width_multiplier" : 2,
"max_num_quads" : 15,
"min_num_quads" : 0,
}
def __init__(self, mobject, direction = DOWN, **kwargs):
digest_config(self, kwargs, locals())
angle = -np.arctan2(*direction[:2]) + np.pi
mobject.rotate(-angle, about_point = ORIGIN)
left = mobject.get_corner(DOWN+LEFT)
right = mobject.get_corner(DOWN+RIGHT)
target_width = right[0]-left[0]
## Adding int(target_width) qquads gives approximately the right width
num_quads = np.clip(
int(self.width_multiplier*target_width),
self.min_num_quads, self.max_num_quads
)
tex_string = "\\underbrace{%s}"%(num_quads*"\\qquad")
TexMobject.__init__(self, tex_string, **kwargs)
self.tip_point_index = np.argmin(self.get_all_points()[:,1])
self.stretch_to_fit_width(target_width)
self.shift(left - self.get_corner(UP+LEFT) + self.buff*DOWN)
for mob in mobject, self:
mob.rotate(angle, about_point = ORIGIN)
def put_at_tip(self, mob, use_next_to = True, **kwargs):
if use_next_to:
mob.next_to(
self.get_tip(),
np.round(self.get_direction()),
**kwargs
)
else:
mob.move_to(self.get_tip())
buff = kwargs.get("buff", DEFAULT_MOBJECT_TO_MOBJECT_BUFFER)
shift_distance = mob.get_width()/2.0+buff
mob.shift(self.get_direction()*shift_distance)
return self
def get_text(self, *text, **kwargs):
text_mob = TextMobject(*text)
self.put_at_tip(text_mob, **kwargs)
return text_mob
def get_tex(self, *tex, **kwargs):
tex_mob = TexMobject(*tex)
self.put_at_tip(tex_mob, **kwargs)
return tex_mob
def get_tip(self):
# Very specific to the LaTeX representation
# of a brace, but it's the only way I can think
# of to get the tip regardless of orientation.
return self.get_all_points()[self.tip_point_index]
def get_direction(self):
vect = self.get_tip() - self.get_center()
return vect/np.linalg.norm(vect)
class BraceLabel(VMobject):
CONFIG = {
"label_constructor" : TexMobject,
"label_scale" : 1,
}
def __init__(self, obj, text, brace_direction = DOWN, **kwargs):
VMobject.__init__(self, **kwargs)
self.brace_direction = brace_direction
if isinstance(obj, list): obj = VMobject(*obj)
self.brace = Brace(obj, brace_direction, **kwargs)
if isinstance(text, tuple) or isinstance(text, list):
self.label = self.label_constructor(*text, **kwargs)
else: self.label = self.label_constructor(str(text))
if self.label_scale != 1: self.label.scale(self.label_scale)
self.brace.put_at_tip(self.label)
self.submobjects = [self.brace, self.label]
def creation_anim(self, label_anim = FadeIn, brace_anim = GrowFromCenter):
return AnimationGroup(brace_anim(self.brace), label_anim(self.label))
def shift_brace(self, obj, **kwargs):
if isinstance(obj, list): obj = VMobject(*obj)
self.brace = Brace(obj, self.brace_direction, **kwargs)
self.brace.put_at_tip(self.label)
self.submobjects[0] = self.brace
return self
def change_label(self, *text, **kwargs):
self.label = self.label_constructor(*text, **kwargs)
if self.label_scale != 1: self.label.scale(self.label_scale)
self.brace.put_at_tip(self.label)
self.submobjects[1] = self.label
return self
def change_brace_label(self, obj, *text):
self.shift_brace(obj)
self.change_label(*text)
return self
def copy(self):
copy_mobject = copy.copy(self)
copy_mobject.brace = self.brace.copy()
copy_mobject.label = self.label.copy()
copy_mobject.submobjects = [copy_mobject.brace, copy_mobject.label]
return copy_mobject
class BraceText(BraceLabel):
CONFIG = {
"label_constructor" : TextMobject
}

View File

@ -1,13 +1,15 @@
from __future__ import absolute_import
from constants import *
from mobject.mobject import Mobject
from mobject.svg_mobject import SVGMobject
from mobject.tex_mobject import Brace
from mobject.tex_mobject import TexMobject
from mobject.tex_mobject import TextMobject
from mobject.vectorized_mobject import VGroup
from mobject.vectorized_mobject import VMobject
from mobject.vectorized_mobject import VectorizedPoint
from mobject.svg.svg_mobject import SVGMobject
from mobject.svg.brace import Brace
from mobject.svg.tex_mobject import TexMobject
from mobject.svg.tex_mobject import TextMobject
from mobject.types.vectorized_mobject import VGroup
from mobject.types.vectorized_mobject import VMobject
from mobject.types.vectorized_mobject import VectorizedPoint
from animation.animation import Animation
from animation.composition import AnimationGroup
@ -17,13 +19,13 @@ from animation.transform import ApplyMethod
from animation.creation import FadeIn
from animation.creation import GrowFromCenter
from topics.geometry import Arc
from topics.geometry import Circle
from topics.geometry import Line
from topics.geometry import Polygon
from topics.geometry import Rectangle
from topics.geometry import Square
from topics.geometry import SurroundingRectangle
from mobject.geometry import Arc
from mobject.geometry import Circle
from mobject.geometry import Line
from mobject.geometry import Polygon
from mobject.geometry import Rectangle
from mobject.geometry import Square
from mobject.shape_matchers import SurroundingRectangle
from topics.three_dimensions import Cube
from utils.config_ops import digest_config
from utils.config_ops import digest_locals
@ -583,131 +585,5 @@ class Car(SVGMobject):
def get_rear_light(self):
return self[1][8]
class MoveCar(ApplyMethod):
CONFIG = {
"moving_forward" : True,
}
def __init__(self, car, target_point, **kwargs):
ApplyMethod.__init__(self, car.move_to, target_point, **kwargs)
displacement = self.target_mobject.get_right()-self.starting_mobject.get_right()
distance = np.linalg.norm(displacement)
if not self.moving_forward:
distance *= -1
tire_radius = car.get_tires()[0].get_width()/2
self.total_tire_radians = -distance/tire_radius
def update_mobject(self, alpha):
ApplyMethod.update_mobject(self, alpha)
if alpha == 0:
return
radians = alpha*self.total_tire_radians
for tire in self.mobject.get_tires():
tire.rotate_in_place(radians)
#TODO: Where should this live?
class Broadcast(LaggedStart):
CONFIG = {
"small_radius" : 0.0,
"big_radius" : 5,
"n_circles" : 5,
"start_stroke_width" : 8,
"color" : WHITE,
"remover" : True,
"lag_ratio" : 0.7,
"run_time" : 3,
"remover" : True,
}
def __init__(self, focal_point, **kwargs):
digest_config(self, kwargs)
circles = VGroup()
for x in range(self.n_circles):
circle = Circle(
radius = self.big_radius,
stroke_color = BLACK,
stroke_width = 0,
)
circle.move_to(focal_point)
circle.save_state()
circle.scale_to_fit_width(self.small_radius*2)
circle.set_stroke(self.color, self.start_stroke_width)
circles.add(circle)
LaggedStart.__init__(
self, ApplyMethod, circles,
lambda c : (c.restore,),
**kwargs
)
class BraceLabel(VMobject):
CONFIG = {
"label_constructor" : TexMobject,
"label_scale" : 1,
}
def __init__(self, obj, text, brace_direction = DOWN, **kwargs):
VMobject.__init__(self, **kwargs)
self.brace_direction = brace_direction
if isinstance(obj, list): obj = VMobject(*obj)
self.brace = Brace(obj, brace_direction, **kwargs)
if isinstance(text, tuple) or isinstance(text, list):
self.label = self.label_constructor(*text, **kwargs)
else: self.label = self.label_constructor(str(text))
if self.label_scale != 1: self.label.scale(self.label_scale)
self.brace.put_at_tip(self.label)
self.submobjects = [self.brace, self.label]
def creation_anim(self, label_anim = FadeIn, brace_anim = GrowFromCenter):
return AnimationGroup(brace_anim(self.brace), label_anim(self.label))
def shift_brace(self, obj, **kwargs):
if isinstance(obj, list): obj = VMobject(*obj)
self.brace = Brace(obj, self.brace_direction, **kwargs)
self.brace.put_at_tip(self.label)
self.submobjects[0] = self.brace
return self
def change_label(self, *text, **kwargs):
self.label = self.label_constructor(*text, **kwargs)
if self.label_scale != 1: self.label.scale(self.label_scale)
self.brace.put_at_tip(self.label)
self.submobjects[1] = self.label
return self
def change_brace_label(self, obj, *text):
self.shift_brace(obj)
self.change_label(*text)
return self
def copy(self):
copy_mobject = copy.copy(self)
copy_mobject.brace = self.brace.copy()
copy_mobject.label = self.label.copy()
copy_mobject.submobjects = [copy_mobject.brace, copy_mobject.label]
return copy_mobject
class BraceText(BraceLabel):
CONFIG = {
"label_constructor" : TextMobject
}
class DashedMobject(VMobject):
CONFIG = {
"dashes_num" : 15,
"spacing" : 0.5,
"color" : WHITE
}
def __init__(self, mob, **kwargs):
digest_locals(self)
VMobject.__init__(self, **kwargs)
buff = float(self.spacing) / self.dashes_num
for i in range(self.dashes_num):
a = ((1+buff) * i)/self.dashes_num
b = 1-((1+buff) * (self.dashes_num-1-i)) / self.dashes_num
dash = VMobject(color = self.color)
dash.pointwise_become_partial(mob, a, b)
self.submobjects.append(dash)

View File

@ -6,13 +6,13 @@ import warnings
from xml.dom import minidom
from constants import *
from topics.geometry import Circle
from topics.geometry import Rectangle
from mobject.geometry import Circle
from mobject.geometry import Rectangle
from utils.bezier import is_closed
from utils.config_ops import digest_config
from utils.config_ops import digest_locals
from vectorized_mobject import VGroup
from vectorized_mobject import VMobject
from mobject.types.vectorized_mobject import VGroup
from mobject.types.vectorized_mobject import VMobject
def string_to_numbers(num_string):
num_string = num_string.replace("-",",-")

View File

@ -2,11 +2,11 @@ from constants import *
from svg_mobject import SVGMobject
from svg_mobject import VMobjectFromSVGPathstring
from topics.geometry import BackgroundRectangle
from mobject.shape_matchers import BackgroundRectangle
from utils.config_ops import digest_config
from vectorized_mobject import VGroup
from vectorized_mobject import VMobject
from vectorized_mobject import VectorizedPoint
from mobject.types.vectorized_mobject import VGroup
from mobject.types.vectorized_mobject import VMobject
from mobject.types.vectorized_mobject import VectorizedPoint
import collections
import operator as op
@ -231,68 +231,6 @@ class TextMobject(TexMobject):
"alignment" : "\\centering",
}
class Brace(TexMobject):
CONFIG = {
"buff" : 0.2,
"width_multiplier" : 2,
"max_num_quads" : 15,
"min_num_quads" : 0,
}
def __init__(self, mobject, direction = DOWN, **kwargs):
digest_config(self, kwargs, locals())
angle = -np.arctan2(*direction[:2]) + np.pi
mobject.rotate(-angle, about_point = ORIGIN)
left = mobject.get_corner(DOWN+LEFT)
right = mobject.get_corner(DOWN+RIGHT)
target_width = right[0]-left[0]
## Adding int(target_width) qquads gives approximately the right width
num_quads = np.clip(
int(self.width_multiplier*target_width),
self.min_num_quads, self.max_num_quads
)
tex_string = "\\underbrace{%s}"%(num_quads*"\\qquad")
TexMobject.__init__(self, tex_string, **kwargs)
self.tip_point_index = np.argmin(self.get_all_points()[:,1])
self.stretch_to_fit_width(target_width)
self.shift(left - self.get_corner(UP+LEFT) + self.buff*DOWN)
for mob in mobject, self:
mob.rotate(angle, about_point = ORIGIN)
def put_at_tip(self, mob, use_next_to = True, **kwargs):
if use_next_to:
mob.next_to(
self.get_tip(),
np.round(self.get_direction()),
**kwargs
)
else:
mob.move_to(self.get_tip())
buff = kwargs.get("buff", DEFAULT_MOBJECT_TO_MOBJECT_BUFFER)
shift_distance = mob.get_width()/2.0+buff
mob.shift(self.get_direction()*shift_distance)
return self
def get_text(self, *text, **kwargs):
text_mob = TextMobject(*text)
self.put_at_tip(text_mob, **kwargs)
return text_mob
def get_tex(self, *tex, **kwargs):
tex_mob = TexMobject(*tex)
self.put_at_tip(tex_mob, **kwargs)
return tex_mob
def get_tip(self):
# Very specific to the LaTeX representation
# of a brace, but it's the only way I can think
# of to get the tip regardless of orientation.
return self.get_all_points()[self.tip_point_index]
def get_direction(self):
vect = self.get_tip() - self.get_center()
return vect/np.linalg.norm(vect)
class BulletedList(TextMobject):
CONFIG = {
"buff" : MED_LARGE_BUFF,

View File

View File

@ -10,7 +10,6 @@ from random import random
from constants import *
from mobject.mobject import Mobject
from mobject.point_cloud_mobject import PMobject
from utils.bezier import interpolate
from utils.color import color_to_int_rgb
from utils.color import interpolate_color

View File

@ -493,3 +493,21 @@ class VectorizedPoint(VMobject):
def set_location(self,new_loc):
self.set_points(np.array([new_loc]))
class DashedMobject(VMobject):
CONFIG = {
"dashes_num" : 15,
"spacing" : 0.5,
"color" : WHITE
}
def __init__(self, mobject, **kwargs):
VMobject.__init__(self, **kwargs)
buff = float(self.spacing) / self.dashes_num
for i in range(self.dashes_num):
a = ((1+buff) * i)/self.dashes_num
b = 1-((1+buff) * (self.dashes_num-1-i)) / self.dashes_num
dash = VMobject(color = self.color)
dash.pointwise_become_partial(mobject, a, b)
self.submobjects.append(dash)

43
mobject/value_tracker.py Normal file
View File

@ -0,0 +1,43 @@
from __future__ import absolute_import
import numpy as np
from constants import *
from mobject.types.vectorized_mobject import VectorizedPoint
# TODO: Rather than using VectorizedPoint, there should be some UndisplayedPointSet type
class ValueTracker(VectorizedPoint):
"""
Note meant to be displayed. Instead the position encodes some
number, often one which another animation or continual_animation
uses for its update function, and by treating it as a mobject it can
still be animated and manipulated just like anything else.
"""
def __init__(self, value = 0, **kwargs):
VectorizedPoint.__init__(self, **kwargs)
self.set_value(value)
def get_value(self):
return self.get_center()[0]
def set_value(self, value):
self.move_to(value*RIGHT)
return self
def increment_value(self, d_value):
self.set_value(self.get_value() + d_value)
class ExponentialValueTracker(ValueTracker):
"""
Operates just like ValueTracker, except it encodes the value as the
exponential of a position coordinate, which changes how interpolation
behaves
"""
def get_value(self):
return np.exp(self.get_center()[0])
def set_value(self, value):
self.move_to(np.log(value)*RIGHT)
return self

View File

@ -7,40 +7,6 @@ from old_projects.fourier import *
FREQUENCY_COLOR = RED
USE_ALMOST_FOURIER_BY_DEFAULT = False
class ValueTracker(VectorizedPoint):
"""
Note meant to be displayed. Instead the position encodes some
number, often one which another animation or continual_animation
uses for its update function, and by treating it as a mobject it can
still be animated and manipulated just like anything else.
"""
def __init__(self, value = 0, **kwargs):
VectorizedPoint.__init__(self, **kwargs)
self.set_value(value)
def get_value(self):
return self.get_center()[0]
def set_value(self, value):
self.move_to(value*RIGHT)
return self
def increment_value(self, d_value):
self.set_value(self.get_value() + d_value)
class ExponentialValueTracker(ValueTracker):
"""
Operates just like ValueTracker, except it encodes the value as the
exponential of a position coordinate, which changes how interpolation
behaves
"""
def get_value(self):
return np.exp(self.get_center()[0])
def set_value(self, value):
self.move_to(np.log(value)*RIGHT)
return self
class GaussianDistributionWrapper(Line):
"""
This is meant to encode a 2d normal distribution as

View File

@ -3,7 +3,7 @@ import numpy as np
from animation.animation import Animation
from constants import *
from mobject.tex_mobject import TexMobject
from mobject.svg.tex_mobject import TexMobject
from scene.scene import Scene
class RearrangeEquation(Scene):

View File

@ -1,7 +1,7 @@
from constants import *
from mobject.tex_mobject import TexMobject
from mobject.vectorized_mobject import VMobject
from mobject.svg.tex_mobject import TexMobject
from mobject.types.vectorized_mobject import VMobject
from scene.scene import Scene
from utils.simple_functions import choose

View File

@ -1,18 +1,18 @@
from constants import *
from mobject.mobject import Mobject
from mobject.tex_mobject import TexMobject
from mobject.tex_mobject import TextMobject
from mobject.vectorized_mobject import VGroup
from mobject.vectorized_mobject import VMobject
from mobject.svg.tex_mobject import TexMobject
from mobject.svg.tex_mobject import TextMobject
from mobject.types.vectorized_mobject import VGroup
from mobject.types.vectorized_mobject import VMobject
from animation.creation import ShowCreation
from animation.creation import FadeIn
from animation.transform import MoveToTarget
from animation.transform import Transform
from topics.geometry import Arrow
from topics.geometry import Circle
from topics.geometry import Dot
from mobject.geometry import Arrow
from mobject.geometry import Circle
from mobject.geometry import Dot
from scene.scene import Scene

View File

@ -3,15 +3,15 @@ from animation.transform import Transform
from pi_creature.pi_creature import PiCreature
from pi_creature.pi_creature import Randolph
from pi_creature.pi_creature import get_all_pi_creature_modes
from mobject.vectorized_mobject import VGroup
from mobject.vectorized_mobject import VMobject
from mobject.vectorized_mobject import VectorizedPoint
from mobject.types.vectorized_mobject import VGroup
from mobject.types.vectorized_mobject import VMobject
from mobject.types.vectorized_mobject import VectorizedPoint
from scene.scene import Scene
from topics.geometry import Circle
from topics.geometry import Line
from topics.geometry import Polygon
from topics.geometry import RegularPolygon
from topics.geometry import Square
from mobject.geometry import Circle
from mobject.geometry import Line
from mobject.geometry import Polygon
from mobject.geometry import RegularPolygon
from mobject.geometry import Square
from utils.bezier import interpolate
from utils.color import color_gradient
from utils.config_ops import digest_config

View File

@ -1,4 +1,34 @@
from big_ol_pile_of_manim_imports import *
from constants import *
from mobject.geometry import AnnularSector
from mobject.geometry import Arc
from mobject.mobject import Mobject
from mobject.svg.svg_mobject import SVGMobject
from mobject.svg.tex_mobject import TexMobject
from mobject.types.vectorized_mobject import VGroup
from mobject.types.vectorized_mobject import VMobject
from mobject.types.vectorized_mobject import VectorizedPoint
from continual_animation.continual_animation import ContinualAnimation
from animation.animation import Animation
from animation.composition import LaggedStart
from animation.transform import ApplyMethod
from animation.transform import Transform
from animation.creation import FadeIn
from animation.creation import FadeOut
from camera.camera import Camera
from scene.scene import Scene
from topics.three_dimensions import ThreeDCamera
from topics.three_dimensions import ThreeDScene
from utils.space_ops import angle_between
from utils.space_ops import angle_between_vectors
from utils.space_ops import project_along_vector
from utils.space_ops import rotate_vector
from utils.space_ops import rotation_matrix
from utils.space_ops import z_to_vector
from scipy.spatial import ConvexHull
from traceback import *

View File

@ -3,12 +3,12 @@ import numpy as np
from constants import *
from mobject.mobject import Mobject
from mobject.svg_mobject import SVGMobject
from mobject.tex_mobject import TextMobject
from mobject.vectorized_mobject import VGroup
from mobject.vectorized_mobject import VMobject
from mobject.svg.svg_mobject import SVGMobject
from mobject.svg.tex_mobject import TextMobject
from mobject.types.vectorized_mobject import VGroup
from mobject.types.vectorized_mobject import VMobject
from topics.objects import ThoughtBubble
from mobject.svg.drawings import ThoughtBubble
from animation.transform import Transform
from utils.config_ops import digest_config

View File

@ -4,7 +4,7 @@ from constants import *
from mobject.mobject import Group
from topics.objects import SpeechBubble
from mobject.svg.drawings import SpeechBubble
from animation.creation import ShowCreation
from animation.creation import Write

View File

@ -6,11 +6,11 @@ import random
from constants import *
from mobject.vectorized_mobject import VGroup
from mobject.types.vectorized_mobject import VGroup
from topics.geometry import ScreenRectangle
from topics.objects import SpeechBubble
from topics.objects import ThoughtBubble
from mobject.frame import ScreenRectangle
from mobject.svg.drawings import SpeechBubble
from mobject.svg.drawings import ThoughtBubble
from animation.transform import ApplyMethod
from animation.transform import ReplacementTransform

View File

@ -4,7 +4,7 @@ from constants import *
from scene.scene import Scene
from camera.moving_camera import MovingCamera
from topics.geometry import ScreenRectangle
from mobject.frame import ScreenRectangle
class MovingCameraScene(Scene):
def setup(self):

View File

@ -20,7 +20,7 @@ from animation.transform import MoveToTarget
from camera.camera import Camera
from continual_animation.continual_animation import ContinualAnimation
from mobject.mobject import Mobject
from mobject.vectorized_mobject import VMobject
from mobject.types.vectorized_mobject import VMobject
from utils.iterables import list_update
from container.container import Container

View File

@ -7,7 +7,7 @@ from animation.creation import FadeIn
from camera.camera import Camera
from camera.moving_camera import MovingCamera
from mobject.mobject import Mobject
from topics.geometry import Rectangle
from mobject.geometry import Rectangle
from constants import *

View File

@ -8,17 +8,17 @@ from animation.creation import Write
from animation.transform import ApplyMethod
from animation.creation import FadeIn
from animation.creation import FadeOut
from mobject.tex_mobject import TexMobject
from mobject.tex_mobject import TextMobject
from mobject.vectorized_mobject import VGroup
from mobject.svg.tex_mobject import TexMobject
from mobject.svg.tex_mobject import TextMobject
from mobject.types.vectorized_mobject import VGroup
from scene.scene import Scene
from pi_creature.pi_creature_animations import Blink
from pi_creature.pi_creature import Mortimer
from pi_creature.pi_creature import Randolph
from topics.geometry import DashedLine
from topics.geometry import Rectangle
from topics.geometry import Square
from topics.objects import PatreonLogo
from mobject.geometry import DashedLine
from mobject.geometry import Rectangle
from mobject.geometry import Square
from mobject.svg.drawings import PatreonLogo
class OpeningQuote(Scene):
CONFIG = {

View File

@ -7,9 +7,9 @@ from animation.creation import ShowCreation
from animation.movement import SmoothedVectorizedHomotopy
from animation.transform import ApplyPointwiseFunction
from animation.transform import MoveToTarget
from mobject.tex_mobject import TexMobject
from mobject.tex_mobject import TextMobject
from mobject.vectorized_mobject import VGroup
from mobject.svg.tex_mobject import TexMobject
from mobject.svg.tex_mobject import TextMobject
from mobject.types.vectorized_mobject import VGroup
from number_line import NumberPlane
from scene.scene import Scene
from utils.config_ops import digest_config

View File

@ -1,6 +1,6 @@
from scipy import integrate
from mobject.vectorized_mobject import VMobject
from mobject.types.vectorized_mobject import VMobject
from utils.config_ops import digest_config
from constants import *

View File

@ -1,19 +1,19 @@
from constants import *
from scene.scene import Scene
# from topics.geometry import
# from mobject.geometry import
from animation.creation import ShowCreation
from animation.update import UpdateFromAlphaFunc
from animation.creation import Write
from animation.transform import Transform
from mobject.tex_mobject import TexMobject
from mobject.tex_mobject import TextMobject
from mobject.vectorized_mobject import VGroup
from mobject.vectorized_mobject import VectorizedPoint
from mobject.svg.tex_mobject import TexMobject
from mobject.svg.tex_mobject import TextMobject
from mobject.types.vectorized_mobject import VGroup
from mobject.types.vectorized_mobject import VectorizedPoint
from topics.functions import ParametricFunction
from topics.geometry import DashedLine
from topics.geometry import Line
from topics.geometry import Rectangle
from mobject.geometry import DashedLine
from mobject.geometry import Line
from mobject.geometry import Rectangle
from topics.number_line import NumberLine
from utils.bezier import interpolate
from utils.color import color_gradient

View File

@ -8,17 +8,17 @@ from animation.transform import ApplyPointwiseFunction
from animation.creation import FadeOut
from animation.transform import Transform
from mobject.mobject import Mobject
from mobject.tex_mobject import TexMobject
from mobject.tex_mobject import TextMobject
from mobject.vectorized_mobject import VGroup
from mobject.vectorized_mobject import VMobject
from mobject.svg.tex_mobject import TexMobject
from mobject.svg.tex_mobject import TextMobject
from mobject.types.vectorized_mobject import VGroup
from mobject.types.vectorized_mobject import VMobject
from scene.scene import Scene
from topics.geometry import Arrow
from topics.geometry import BackgroundRectangle
from topics.geometry import Circle
from topics.geometry import Dot
from topics.geometry import Line
from topics.geometry import Vector
from mobject.geometry import Arrow
from mobject.shape_matchers import BackgroundRectangle
from mobject.geometry import Circle
from mobject.geometry import Dot
from mobject.geometry import Line
from mobject.geometry import Vector
from topics.number_line import Axes
from topics.number_line import NumberPlane

View File

@ -1,12 +1,12 @@
from constants import *
from mobject.tex_mobject import TexMobject
from mobject.vectorized_mobject import VGroup
from mobject.vectorized_mobject import VMobject
from mobject.svg.tex_mobject import TexMobject
from mobject.types.vectorized_mobject import VGroup
from mobject.types.vectorized_mobject import VMobject
from scene.scene import Scene
from topics.functions import ParametricFunction
from topics.geometry import Arrow
from topics.geometry import Line
from mobject.geometry import Arrow
from mobject.geometry import Line
from utils.bezier import interpolate
from utils.config_ops import digest_config
from utils.space_ops import angle_of_vector

View File

@ -2,12 +2,12 @@
from animation.animation import Animation
from constants import *
from continual_animation.continual_animation import ContinualAnimation
from mobject.tex_mobject import TexMobject
from mobject.vectorized_mobject import VGroup
from mobject.vectorized_mobject import VMobject
from mobject.vectorized_mobject import VectorizedPoint
from mobject.svg.tex_mobject import TexMobject
from mobject.types.vectorized_mobject import VGroup
from mobject.types.vectorized_mobject import VMobject
from mobject.types.vectorized_mobject import VectorizedPoint
from scene.scene import Scene
from topics.geometry import BackgroundRectangle
from mobject.shape_matchers import BackgroundRectangle
from utils.bezier import interpolate
from utils.config_ops import digest_config

View File

@ -8,19 +8,19 @@ from animation.transform import Transform
from animation.update import UpdateFromFunc
from mobject.mobject import Mobject
from mobject.svg_mobject import SVGMobject
from mobject.tex_mobject import Brace
from mobject.tex_mobject import TexMobject
from mobject.tex_mobject import TextMobject
from mobject.vectorized_mobject import VGroup
from mobject.vectorized_mobject import VMobject
from mobject.vectorized_mobject import VectorizedPoint
from topics.geometry import Arc
from topics.geometry import Circle
from topics.geometry import Line
from topics.geometry import Polygon
from topics.geometry import Rectangle
from topics.geometry import Square
from mobject.svg.svg_mobject import SVGMobject
from mobject.svg.brace import Brace
from mobject.svg.tex_mobject import TexMobject
from mobject.svg.tex_mobject import TextMobject
from mobject.types.vectorized_mobject import VGroup
from mobject.types.vectorized_mobject import VMobject
from mobject.types.vectorized_mobject import VectorizedPoint
from mobject.geometry import Arc
from mobject.geometry import Circle
from mobject.geometry import Line
from mobject.geometry import Polygon
from mobject.geometry import Rectangle
from mobject.geometry import Square
from utils.bezier import interpolate
from utils.color import average_color

View File

@ -4,12 +4,12 @@ from constants import *
from continual_animation.continual_animation import ContinualMovement
from animation.transform import ApplyMethod
from camera.camera import Camera
from mobject.vectorized_mobject import VGroup
from mobject.vectorized_mobject import VMobject
from mobject.vectorized_mobject import VectorizedPoint
from mobject.types.vectorized_mobject import VGroup
from mobject.types.vectorized_mobject import VMobject
from mobject.types.vectorized_mobject import VectorizedPoint
from scene.scene import Scene
from topics.geometry import Line
from topics.geometry import Square
from mobject.geometry import Line
from mobject.geometry import Square
from utils.bezier import interpolate
from utils.iterables import list_update

View File

@ -9,18 +9,18 @@ from animation.transform import ApplyPointwiseFunction
from animation.creation import FadeOut
from animation.transform import Transform
from mobject.mobject import Mobject
from mobject.tex_mobject import TexMobject
from mobject.tex_mobject import TextMobject
from mobject.vectorized_mobject import VGroup
from mobject.vectorized_mobject import VMobject
from mobject.svg.tex_mobject import TexMobject
from mobject.svg.tex_mobject import TextMobject
from mobject.types.vectorized_mobject import VGroup
from mobject.types.vectorized_mobject import VMobject
from scene.scene import Scene
from topics.geometry import Arrow
from topics.geometry import BackgroundRectangle
from topics.geometry import Circle
from topics.geometry import Dot
from topics.geometry import Line
from topics.geometry import Square
from topics.geometry import Vector
from mobject.geometry import Arrow
from mobject.shape_matchers import BackgroundRectangle
from mobject.geometry import Circle
from mobject.geometry import Dot
from mobject.geometry import Line
from mobject.geometry import Square
from mobject.geometry import Vector
from topics.number_line import Axes
from topics.number_line import NumberPlane

View File

@ -101,12 +101,3 @@ def center_of_mass(points):
points = [np.array(point).astype("float") for point in points]
return sum(points) / len(points)
# TODO: It feels like this should live elsewhere