2015-06-10 22:00:35 -07:00
|
|
|
from helpers import *
|
|
|
|
|
2016-04-19 00:20:19 -07:00
|
|
|
from mobject import Mobject
|
2017-06-14 21:54:21 -07:00
|
|
|
from mobject.vectorized_mobject import VMobject, VGroup
|
2015-10-27 21:00:50 -07:00
|
|
|
|
2016-04-17 00:31:38 -07:00
|
|
|
class Arc(VMobject):
|
2016-02-27 16:32:53 -08:00
|
|
|
CONFIG = {
|
2016-04-17 00:31:38 -07:00
|
|
|
"radius" : 1.0,
|
|
|
|
"start_angle" : 0,
|
2016-11-07 14:22:27 -08:00
|
|
|
"num_anchors" : 9,
|
2016-07-13 13:09:18 -07:00
|
|
|
"anchors_span_full_range" : True,
|
2015-09-28 16:25:18 -07:00
|
|
|
}
|
2016-04-17 00:31:38 -07:00
|
|
|
def __init__(self, angle, **kwargs):
|
2015-10-28 16:03:33 -07:00
|
|
|
digest_locals(self)
|
2016-04-17 00:31:38 -07:00
|
|
|
VMobject.__init__(self, **kwargs)
|
2015-06-10 22:00:35 -07:00
|
|
|
|
|
|
|
def generate_points(self):
|
2016-04-17 00:31:38 -07:00
|
|
|
self.set_anchor_points(
|
|
|
|
self.get_unscaled_anchor_points(),
|
|
|
|
mode = "smooth"
|
|
|
|
)
|
|
|
|
self.scale(self.radius)
|
|
|
|
|
|
|
|
def get_unscaled_anchor_points(self):
|
|
|
|
return [
|
|
|
|
np.cos(a)*RIGHT+np.sin(a)*UP
|
2016-07-12 15:16:20 -07:00
|
|
|
for a in np.linspace(
|
|
|
|
self.start_angle,
|
|
|
|
self.start_angle + self.angle,
|
|
|
|
self.num_anchors
|
2016-04-17 00:31:38 -07:00
|
|
|
)
|
|
|
|
]
|
2015-06-10 22:00:35 -07:00
|
|
|
|
2016-11-18 21:23:52 -08:00
|
|
|
def add_tip(self, tip_length = 0.25):
|
2016-08-03 16:51:16 -07:00
|
|
|
#TODO, do this a better way
|
2016-11-18 21:23:52 -08:00
|
|
|
arrow = Arrow(*self.points[-2:], tip_length = tip_length)
|
2016-08-03 16:51:16 -07:00
|
|
|
self.add(arrow.split()[-1])
|
|
|
|
self.highlight(self.get_color())
|
|
|
|
return self
|
|
|
|
|
2016-04-17 00:31:38 -07:00
|
|
|
class Circle(Arc):
|
2016-02-27 16:32:53 -08:00
|
|
|
CONFIG = {
|
2016-04-17 00:31:38 -07:00
|
|
|
"color" : RED,
|
|
|
|
"close_new_points" : True,
|
|
|
|
"anchors_span_full_range" : False
|
2015-09-28 16:25:18 -07:00
|
|
|
}
|
2016-04-17 00:31:38 -07:00
|
|
|
def __init__(self, **kwargs):
|
|
|
|
Arc.__init__(self, 2*np.pi, **kwargs)
|
2015-09-28 16:25:18 -07:00
|
|
|
|
2017-07-20 13:37:12 -07:00
|
|
|
class Dot(Circle):
|
2016-04-17 00:31:38 -07:00
|
|
|
CONFIG = {
|
2016-10-26 17:17:07 -07:00
|
|
|
"radius" : 0.08,
|
2016-04-17 00:31:38 -07:00
|
|
|
"stroke_width" : 0,
|
2016-07-22 11:22:31 -07:00
|
|
|
"fill_opacity" : 1.0,
|
|
|
|
"color" : WHITE
|
2016-04-17 00:31:38 -07:00
|
|
|
}
|
2016-04-17 19:29:27 -07:00
|
|
|
def __init__(self, point = ORIGIN, **kwargs):
|
|
|
|
Circle.__init__(self, **kwargs)
|
|
|
|
self.shift(point)
|
|
|
|
self.init_colors()
|
2015-06-10 22:00:35 -07:00
|
|
|
|
2016-04-17 00:31:38 -07:00
|
|
|
class Line(VMobject):
|
2016-02-27 16:32:53 -08:00
|
|
|
CONFIG = {
|
2016-04-17 00:31:38 -07:00
|
|
|
"buff" : 0,
|
2016-08-02 12:26:15 -07:00
|
|
|
"considered_smooth" : False,
|
2017-04-26 16:21:38 -07:00
|
|
|
"path_arc" : None,
|
|
|
|
"n_arc_anchors" : 10, #Only used if path_arc is not None
|
2015-12-19 13:06:09 -08:00
|
|
|
}
|
2015-09-28 16:25:18 -07:00
|
|
|
def __init__(self, start, end, **kwargs):
|
2015-12-19 13:06:09 -08:00
|
|
|
digest_config(self, kwargs)
|
2015-08-17 11:12:56 -07:00
|
|
|
self.set_start_and_end(start, end)
|
2016-04-17 00:31:38 -07:00
|
|
|
VMobject.__init__(self, **kwargs)
|
2015-06-10 22:00:35 -07:00
|
|
|
|
2017-04-26 16:21:38 -07:00
|
|
|
def generate_points(self):
|
|
|
|
if self.path_arc is None:
|
|
|
|
self.set_points_as_corners([self.start, self.end])
|
|
|
|
else:
|
|
|
|
path_func = path_along_arc(self.path_arc)
|
|
|
|
self.set_points_smoothly([
|
|
|
|
path_func(self.start, self.end, alpha)
|
|
|
|
for alpha in np.linspace(0, 1, self.n_arc_anchors)
|
|
|
|
])
|
|
|
|
self.considered_smooth = True
|
2017-04-26 16:40:54 -07:00
|
|
|
self.account_for_buff()
|
|
|
|
|
|
|
|
def account_for_buff(self):
|
|
|
|
anchors = self.get_anchors()
|
|
|
|
length = sum([
|
|
|
|
np.linalg.norm(a2-a1)
|
|
|
|
for a1, a2 in zip(anchors, anchors[1:])
|
|
|
|
])
|
|
|
|
if length < 2*self.buff or self.buff == 0:
|
|
|
|
return
|
|
|
|
buff_proportion = self.buff / length
|
|
|
|
self.pointwise_become_partial(
|
|
|
|
self, buff_proportion, 1 - buff_proportion
|
|
|
|
)
|
2017-04-26 16:21:38 -07:00
|
|
|
|
2015-08-17 11:12:56 -07:00
|
|
|
def set_start_and_end(self, start, end):
|
2016-04-17 00:31:38 -07:00
|
|
|
start_to_end = self.pointify(end) - self.pointify(start)
|
2015-11-02 19:09:55 -08:00
|
|
|
vect = np.zeros(len(start_to_end))
|
2015-08-17 11:12:56 -07:00
|
|
|
longer_dim = np.argmax(map(abs, start_to_end))
|
2015-11-02 19:09:55 -08:00
|
|
|
vect[longer_dim] = start_to_end[longer_dim]
|
2015-08-17 11:12:56 -07:00
|
|
|
self.start, self.end = [
|
2015-11-02 19:09:55 -08:00
|
|
|
arg.get_edge_center(unit*vect)
|
2015-08-17 11:12:56 -07:00
|
|
|
if isinstance(arg, Mobject)
|
|
|
|
else np.array(arg)
|
|
|
|
for arg, unit in zip([start, end], [1, -1])
|
|
|
|
]
|
|
|
|
|
2016-04-17 00:31:38 -07:00
|
|
|
def pointify(self, mob_or_point):
|
|
|
|
if isinstance(mob_or_point, Mobject):
|
|
|
|
return mob_or_point.get_center()
|
2016-04-20 19:24:54 -07:00
|
|
|
return np.array(mob_or_point)
|
2016-04-17 00:31:38 -07:00
|
|
|
|
2015-06-13 19:00:23 -07:00
|
|
|
def get_length(self):
|
2016-04-27 17:35:04 -07:00
|
|
|
start, end = self.get_start_and_end()
|
|
|
|
return np.linalg.norm(start - end)
|
2015-06-13 19:00:23 -07:00
|
|
|
|
2016-03-21 19:30:09 -07:00
|
|
|
def get_start_and_end(self):
|
2016-04-27 17:35:04 -07:00
|
|
|
return self.get_start(), self.get_end()
|
|
|
|
|
|
|
|
def get_start(self):
|
2017-05-25 15:12:18 -07:00
|
|
|
return np.array(self.points[0])
|
2016-04-27 17:35:04 -07:00
|
|
|
|
|
|
|
def get_end(self):
|
2017-05-25 15:12:18 -07:00
|
|
|
return np.array(self.points[-1])
|
2016-03-21 19:30:09 -07:00
|
|
|
|
2015-06-13 19:00:23 -07:00
|
|
|
def get_slope(self):
|
2017-04-26 16:21:38 -07:00
|
|
|
start, end = self.get_start_and_end()
|
2015-06-13 19:00:23 -07:00
|
|
|
rise, run = [
|
2016-03-21 19:30:09 -07:00
|
|
|
float(end[i] - start[i])
|
2015-06-13 19:00:23 -07:00
|
|
|
for i in [1, 0]
|
|
|
|
]
|
2016-03-21 19:30:09 -07:00
|
|
|
return np.inf if run == 0 else rise/run
|
|
|
|
|
|
|
|
def get_angle(self):
|
|
|
|
start, end = self.get_start_and_end()
|
2016-03-27 13:57:52 -07:00
|
|
|
return angle_of_vector(end-start)
|
2015-06-13 19:00:23 -07:00
|
|
|
|
2016-04-27 17:35:04 -07:00
|
|
|
def put_start_and_end_on(self, new_start, new_end):
|
2017-08-24 19:06:34 -07:00
|
|
|
self.set_start_and_end(new_start, new_end)
|
|
|
|
self.buff = 0
|
|
|
|
self.generate_points()
|
2016-04-27 17:35:04 -07:00
|
|
|
|
2016-08-18 12:54:04 -07:00
|
|
|
class DashedLine(Line):
|
|
|
|
CONFIG = {
|
2017-01-27 19:31:20 -08:00
|
|
|
"dashed_segment_length" : 0.05
|
2016-08-18 12:54:04 -07:00
|
|
|
}
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
self.init_kwargs = kwargs
|
|
|
|
Line.__init__(self, *args, **kwargs)
|
|
|
|
|
|
|
|
def generate_points(self):
|
|
|
|
length = np.linalg.norm(self.end-self.start)
|
|
|
|
num_interp_points = int(length/self.dashed_segment_length)
|
|
|
|
points = [
|
|
|
|
interpolate(self.start, self.end, alpha)
|
|
|
|
for alpha in np.linspace(0, 1, num_interp_points)
|
|
|
|
]
|
|
|
|
includes = it.cycle([True, False])
|
|
|
|
for p1, p2, include in zip(points, points[1:], includes):
|
|
|
|
if include:
|
|
|
|
self.add(Line(p1, p2, **self.init_kwargs))
|
2017-02-16 13:03:26 -08:00
|
|
|
self.put_start_and_end_on(self.start, self.end)
|
2016-08-18 12:54:04 -07:00
|
|
|
return self
|
|
|
|
|
|
|
|
def get_start(self):
|
2017-02-27 15:56:22 -08:00
|
|
|
if len(self) > 0:
|
|
|
|
return self[0].points[0]
|
|
|
|
else:
|
|
|
|
return self.start
|
2016-08-18 12:54:04 -07:00
|
|
|
|
|
|
|
def get_end(self):
|
2017-02-27 15:56:22 -08:00
|
|
|
if len(self) > 0:
|
|
|
|
return self[-1].points[-1]
|
|
|
|
else:
|
|
|
|
return self.end
|
2016-08-18 12:54:04 -07:00
|
|
|
|
2015-08-17 11:12:56 -07:00
|
|
|
class Arrow(Line):
|
2016-02-27 16:32:53 -08:00
|
|
|
CONFIG = {
|
2015-12-22 11:04:36 -08:00
|
|
|
"color" : YELLOW_C,
|
2015-12-19 13:06:09 -08:00
|
|
|
"tip_length" : 0.25,
|
2017-08-24 19:06:34 -07:00
|
|
|
"tip_width_to_length_ratio" : 1,
|
2017-08-25 17:56:55 -07:00
|
|
|
"max_tip_length_to_length_ratio" : 0.35,
|
|
|
|
"max_stem_width_to_tip_width_ratio" : 0.3,
|
2017-02-07 13:45:10 -08:00
|
|
|
"buff" : MED_SMALL_BUFF,
|
2016-07-16 13:34:21 -07:00
|
|
|
"propogate_style_to_family" : False,
|
2016-04-27 17:35:04 -07:00
|
|
|
"preserve_tip_size_when_scaling" : True,
|
2017-08-24 23:10:39 -07:00
|
|
|
"normal_vector" : OUT,
|
|
|
|
"use_rectangular_stem" : True,
|
|
|
|
"rectangular_stem_width" : 0.05,
|
2015-09-28 16:25:18 -07:00
|
|
|
}
|
2015-08-12 14:24:36 -07:00
|
|
|
def __init__(self, *args, **kwargs):
|
2017-02-27 15:56:22 -08:00
|
|
|
points = map(self.pointify, args)
|
2015-12-31 09:24:02 -08:00
|
|
|
if len(args) == 1:
|
2017-02-27 15:56:22 -08:00
|
|
|
args = (points[0]+UP+LEFT, points[0])
|
2015-08-12 14:24:36 -07:00
|
|
|
Line.__init__(self, *args, **kwargs)
|
2015-09-28 16:25:18 -07:00
|
|
|
self.add_tip()
|
2017-08-24 23:10:39 -07:00
|
|
|
if self.use_rectangular_stem and not hasattr(self, "rect"):
|
|
|
|
self.add_rectangular_stem()
|
2015-08-12 14:24:36 -07:00
|
|
|
|
2016-07-12 10:34:35 -07:00
|
|
|
def add_tip(self, add_at_end = True):
|
2017-05-05 11:19:10 -07:00
|
|
|
tip = VMobject(
|
|
|
|
close_new_points = True,
|
|
|
|
mark_paths_closed = True,
|
|
|
|
fill_color = self.color,
|
|
|
|
fill_opacity = 1,
|
|
|
|
stroke_color = self.color,
|
|
|
|
)
|
|
|
|
self.set_tip_points(tip, add_at_end)
|
|
|
|
self.tip = tip
|
|
|
|
self.add(self.tip)
|
|
|
|
self.init_colors()
|
|
|
|
|
2017-08-24 23:10:39 -07:00
|
|
|
def add_rectangular_stem(self):
|
|
|
|
self.rect = Rectangle(
|
|
|
|
stroke_width = 0,
|
|
|
|
fill_color = self.tip.get_fill_color(),
|
|
|
|
fill_opacity = self.tip.get_fill_opacity()
|
|
|
|
)
|
2017-08-24 23:17:26 -07:00
|
|
|
self.add_to_back(self.rect)
|
2017-08-24 23:10:39 -07:00
|
|
|
self.set_stroke(width = 0)
|
|
|
|
self.set_rectangular_stem_points()
|
|
|
|
|
|
|
|
def set_rectangular_stem_points(self):
|
|
|
|
start, end = self.get_start_and_end()
|
|
|
|
vect = end - start
|
|
|
|
tip_base_points = self.tip.get_anchors()[1:]
|
|
|
|
tip_base = center_of_mass(tip_base_points)
|
|
|
|
tbp1, tbp2 = tip_base_points
|
|
|
|
perp_vect = tbp2 - tbp1
|
2017-08-25 17:56:55 -07:00
|
|
|
tip_base_width = np.linalg.norm(perp_vect)
|
|
|
|
perp_vect /= tip_base_width
|
|
|
|
width = min(
|
|
|
|
self.rectangular_stem_width,
|
|
|
|
self.max_stem_width_to_tip_width_ratio*tip_base_width,
|
|
|
|
)
|
2017-08-24 23:10:39 -07:00
|
|
|
self.rect.set_points_as_corners([
|
|
|
|
tip_base + perp_vect*width/2,
|
2017-08-24 23:17:26 -07:00
|
|
|
start + perp_vect*width/2,
|
2017-08-24 23:10:39 -07:00
|
|
|
start - perp_vect*width/2,
|
2017-08-24 23:17:26 -07:00
|
|
|
tip_base - perp_vect*width/2,
|
2017-08-24 23:10:39 -07:00
|
|
|
])
|
|
|
|
return self
|
|
|
|
|
2017-08-24 19:06:34 -07:00
|
|
|
def set_tip_points(self, tip, add_at_end = True, tip_length = None):
|
|
|
|
if tip_length is None:
|
|
|
|
tip_length = self.tip_length
|
|
|
|
line_length = np.linalg.norm(self.points[-1]-self.points[0])
|
|
|
|
tip_length = min(
|
|
|
|
tip_length, self.max_tip_length_to_length_ratio*line_length
|
2016-04-17 00:31:38 -07:00
|
|
|
)
|
2017-08-24 19:06:34 -07:00
|
|
|
|
|
|
|
indices = (-2, -1) if add_at_end else (1, 0)
|
|
|
|
pre_end_point, end_point = [
|
|
|
|
self.points[index]
|
|
|
|
for index in indices
|
|
|
|
]
|
|
|
|
vect = end_point - pre_end_point
|
2017-08-24 23:10:39 -07:00
|
|
|
perp_vect = np.cross(vect, self.normal_vector)
|
2017-08-24 19:06:34 -07:00
|
|
|
for v in vect, perp_vect:
|
|
|
|
if np.linalg.norm(v) == 0:
|
|
|
|
v[0] = 1
|
|
|
|
v *= tip_length/np.linalg.norm(v)
|
|
|
|
|
|
|
|
ratio = self.tip_width_to_length_ratio
|
|
|
|
tip.set_points_as_corners([
|
|
|
|
end_point,
|
|
|
|
end_point-vect+perp_vect*ratio/2,
|
|
|
|
end_point-vect-perp_vect*ratio/2,
|
|
|
|
])
|
|
|
|
# tip.scale(tip_length, about_point = end_point)
|
|
|
|
|
2017-05-05 11:19:10 -07:00
|
|
|
return self
|
2015-08-12 14:24:36 -07:00
|
|
|
|
2017-02-27 15:56:22 -08:00
|
|
|
def get_end(self):
|
|
|
|
if hasattr(self, "tip"):
|
2017-08-24 23:10:39 -07:00
|
|
|
return self.tip.get_anchors()[0]
|
2017-02-27 15:56:22 -08:00
|
|
|
else:
|
|
|
|
return Line.get_end(self)
|
|
|
|
|
2016-09-14 13:53:23 -07:00
|
|
|
def get_tip(self):
|
|
|
|
return self.tip
|
|
|
|
|
2017-08-24 19:06:34 -07:00
|
|
|
def put_start_and_end_on(self, *args, **kwargs):
|
|
|
|
Line.put_start_and_end_on(self, *args, **kwargs)
|
|
|
|
self.set_tip_points(self.tip)
|
2017-08-24 23:10:39 -07:00
|
|
|
self.set_rectangular_stem_points()
|
2017-08-24 19:06:34 -07:00
|
|
|
|
2017-03-14 15:50:16 -07:00
|
|
|
def scale(self, scale_factor, **kwargs):
|
|
|
|
Line.scale(self, scale_factor, **kwargs)
|
2017-08-24 23:10:39 -07:00
|
|
|
self.set_rectangular_stem_points()
|
2017-08-24 19:06:34 -07:00
|
|
|
if self.preserve_tip_size_when_scaling:
|
2017-05-05 11:19:10 -07:00
|
|
|
self.set_tip_points(self.tip)
|
2016-07-13 13:09:18 -07:00
|
|
|
return self
|
2016-04-27 17:35:04 -07:00
|
|
|
|
2016-03-17 23:54:28 -07:00
|
|
|
class Vector(Arrow):
|
|
|
|
CONFIG = {
|
2016-07-13 22:03:31 -07:00
|
|
|
"color" : YELLOW,
|
2016-03-17 23:54:28 -07:00
|
|
|
"buff" : 0,
|
|
|
|
}
|
2016-04-27 17:35:04 -07:00
|
|
|
def __init__(self, direction, **kwargs):
|
2016-07-15 18:16:06 -07:00
|
|
|
if len(direction) == 2:
|
|
|
|
direction = np.append(np.array(direction), 0)
|
2016-04-27 17:35:04 -07:00
|
|
|
Arrow.__init__(self, ORIGIN, direction, **kwargs)
|
2016-03-17 23:54:28 -07:00
|
|
|
|
2016-04-23 23:36:05 -07:00
|
|
|
class DoubleArrow(Arrow):
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
Arrow.__init__(self, *args, **kwargs)
|
2016-07-12 10:34:35 -07:00
|
|
|
self.add_tip(add_at_end = False)
|
|
|
|
|
2016-04-17 00:31:38 -07:00
|
|
|
class CubicBezier(VMobject):
|
|
|
|
def __init__(self, points, **kwargs):
|
|
|
|
VMobject.__init__(self, **kwargs)
|
|
|
|
self.set_points(points)
|
2015-10-20 21:55:46 -07:00
|
|
|
|
2016-04-17 00:31:38 -07:00
|
|
|
class Polygon(VMobject):
|
2016-02-27 16:32:53 -08:00
|
|
|
CONFIG = {
|
2016-04-17 00:31:38 -07:00
|
|
|
"color" : GREEN_D,
|
2016-04-19 00:20:19 -07:00
|
|
|
"mark_paths_closed" : True,
|
|
|
|
"close_new_points" : True,
|
2016-08-02 12:26:15 -07:00
|
|
|
"considered_smooth" : False,
|
2015-10-08 11:50:49 -07:00
|
|
|
}
|
2016-01-09 20:10:06 -08:00
|
|
|
def __init__(self, *vertices, **kwargs):
|
|
|
|
assert len(vertices) > 1
|
2015-10-28 16:03:33 -07:00
|
|
|
digest_locals(self)
|
2016-04-17 00:31:38 -07:00
|
|
|
VMobject.__init__(self, **kwargs)
|
2015-10-08 11:50:49 -07:00
|
|
|
|
|
|
|
def generate_points(self):
|
2016-04-17 00:31:38 -07:00
|
|
|
self.set_anchor_points(self.vertices, mode = "corners")
|
2015-10-09 19:53:38 -07:00
|
|
|
|
|
|
|
def get_vertices(self):
|
2016-04-17 00:31:38 -07:00
|
|
|
return self.get_anchors_and_handles()[0]
|
2015-12-19 13:06:09 -08:00
|
|
|
|
2017-01-16 11:43:59 -08:00
|
|
|
class RegularPolygon(Polygon):
|
2016-04-27 17:35:04 -07:00
|
|
|
CONFIG = {
|
|
|
|
"start_angle" : 0
|
|
|
|
}
|
|
|
|
def __init__(self, n = 3, **kwargs):
|
|
|
|
digest_config(self, kwargs, locals())
|
|
|
|
start_vect = rotate_vector(RIGHT, self.start_angle)
|
2017-01-16 11:43:59 -08:00
|
|
|
vertices = compass_directions(n, start_vect)
|
2016-04-27 17:35:04 -07:00
|
|
|
Polygon.__init__(self, *vertices, **kwargs)
|
|
|
|
|
2016-04-17 00:31:38 -07:00
|
|
|
class Rectangle(VMobject):
|
2016-02-27 16:32:53 -08:00
|
|
|
CONFIG = {
|
2016-10-25 17:35:16 -07:00
|
|
|
"color" : WHITE,
|
2015-09-28 16:25:18 -07:00
|
|
|
"height" : 2.0,
|
2015-12-19 13:06:09 -08:00
|
|
|
"width" : 4.0,
|
2016-04-19 00:20:19 -07:00
|
|
|
"mark_paths_closed" : True,
|
|
|
|
"close_new_points" : True,
|
2016-08-02 12:26:15 -07:00
|
|
|
"considered_smooth" : False,
|
2015-09-28 16:25:18 -07:00
|
|
|
}
|
2015-08-07 18:10:00 -07:00
|
|
|
def generate_points(self):
|
2016-07-12 15:16:20 -07:00
|
|
|
y, x = self.height/2., self.width/2.
|
2016-04-17 00:31:38 -07:00
|
|
|
self.set_anchor_points([
|
|
|
|
x*LEFT+y*UP,
|
|
|
|
x*RIGHT+y*UP,
|
|
|
|
x*RIGHT+y*DOWN,
|
|
|
|
x*LEFT+y*DOWN
|
|
|
|
], mode = "corners")
|
2015-08-07 18:10:00 -07:00
|
|
|
|
|
|
|
class Square(Rectangle):
|
2016-02-27 16:32:53 -08:00
|
|
|
CONFIG = {
|
2015-10-09 19:53:38 -07:00
|
|
|
"side_length" : 2.0,
|
2015-09-28 16:25:18 -07:00
|
|
|
}
|
|
|
|
def __init__(self, **kwargs):
|
2016-03-19 17:19:02 -07:00
|
|
|
digest_config(self, kwargs)
|
2016-03-07 19:07:00 -08:00
|
|
|
Rectangle.__init__(
|
|
|
|
self,
|
2016-03-19 17:19:02 -07:00
|
|
|
height = self.side_length,
|
|
|
|
width = self.side_length,
|
2016-03-07 19:07:00 -08:00
|
|
|
**kwargs
|
|
|
|
)
|
2015-10-28 16:03:33 -07:00
|
|
|
|
2017-05-14 21:42:33 -07:00
|
|
|
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):
|
2016-07-26 12:32:51 -07:00
|
|
|
CONFIG = {
|
|
|
|
"color" : BLACK,
|
|
|
|
"stroke_width" : 0,
|
|
|
|
"fill_opacity" : 0.75,
|
2017-05-14 21:42:33 -07:00
|
|
|
"buff" : 0
|
2016-07-26 12:32:51 -07:00
|
|
|
}
|
|
|
|
def __init__(self, mobject, **kwargs):
|
2017-05-14 21:42:33 -07:00
|
|
|
SurroundingRectangle.__init__(self, mobject, **kwargs)
|
2016-07-26 12:32:51 -07:00
|
|
|
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
|
|
|
|
|
2016-08-25 17:15:48 -07:00
|
|
|
def get_fill_color(self):
|
|
|
|
return Color(self.color)
|
2016-07-26 12:32:51 -07:00
|
|
|
|
2017-04-27 22:22:42 -07:00
|
|
|
class FullScreenFadeRectangle(Rectangle):
|
|
|
|
CONFIG = {
|
|
|
|
"height" : 2*SPACE_HEIGHT,
|
|
|
|
"width" : 2*SPACE_WIDTH,
|
|
|
|
"stroke_width" : 0,
|
|
|
|
"fill_color" : BLACK,
|
|
|
|
"fill_opacity" : 0.7,
|
|
|
|
}
|
|
|
|
|
2017-05-02 21:09:56 -07:00
|
|
|
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)
|
2017-04-27 22:22:42 -07:00
|
|
|
|
2016-10-25 17:35:16 -07:00
|
|
|
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)
|
2017-08-07 16:17:35 -07:00
|
|
|
|
2017-06-14 21:54:21 -07:00
|
|
|
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)
|
2015-10-28 16:03:33 -07:00
|
|
|
|
2016-04-17 00:31:38 -07:00
|
|
|
class Grid(VMobject):
|
2016-02-27 16:32:53 -08:00
|
|
|
CONFIG = {
|
2016-04-17 00:31:38 -07:00
|
|
|
"height" : 6.0,
|
|
|
|
"width" : 6.0,
|
2016-08-02 12:26:15 -07:00
|
|
|
"considered_smooth" : False,
|
2016-01-26 10:23:05 -08:00
|
|
|
}
|
2016-04-17 00:31:38 -07:00
|
|
|
def __init__(self, rows, columns, **kwargs):
|
|
|
|
digest_config(self, kwargs, locals())
|
|
|
|
VMobject.__init__(self, **kwargs)
|
|
|
|
|
2016-01-26 10:23:05 -08:00
|
|
|
def generate_points(self):
|
2016-04-17 00:31:38 -07:00
|
|
|
x_step = self.width / self.columns
|
|
|
|
y_step = self.height / self.rows
|
|
|
|
|
|
|
|
for x in np.arange(0, self.width+x_step, x_step):
|
|
|
|
self.add(Line(
|
|
|
|
[x-self.width/2., -self.height/2., 0],
|
|
|
|
[x-self.width/2., self.height/2., 0],
|
|
|
|
))
|
|
|
|
for y in np.arange(0, self.height+y_step, y_step):
|
|
|
|
self.add(Line(
|
|
|
|
[-self.width/2., y-self.height/2., 0],
|
|
|
|
[self.width/2., y-self.height/2., 0]
|
|
|
|
))
|
2016-01-26 10:23:05 -08:00
|
|
|
|
2015-10-28 16:03:33 -07:00
|
|
|
|
|
|
|
|