Changed how functions are applied to vectorized mobjects to handle smoothness issues more cleanly

This commit is contained in:
Grant Sanderson 2018-01-17 16:04:07 -08:00
parent 1b67abd8a9
commit f64c076e7e
4 changed files with 35 additions and 23 deletions

View file

@ -14,8 +14,9 @@ class VMobject(Mobject):
"is_subpath" : False,
"close_new_points" : False,
"mark_paths_closed" : False,
"considered_smooth" : True,
"propagate_style_to_family" : False,
"pre_function_handle_to_anchor_scale_factor" : 0.01,
"make_smooth_after_applying_functions" : False,
}
## Colors
@ -191,7 +192,6 @@ class VMobject(Mobject):
return self
def make_smooth(self):
self.considered_smooth = True
return self.change_anchor_mode("smooth")
def make_jagged(self):
@ -232,12 +232,35 @@ class VMobject(Mobject):
self.submobjects
)
def apply_function(self, function, maintain_smoothness = False):
def apply_function(self, function):
factor = self.pre_function_handle_to_anchor_scale_factor
self.scale_handle_to_anchor_distances(factor)
Mobject.apply_function(self, function)
if maintain_smoothness and self.considered_smooth:
self.scale_handle_to_anchor_distances(1./factor)
if self.make_smooth_after_applying_functions:
self.make_smooth()
return self
def scale_handle_to_anchor_distances(self, factor):
"""
If the distance between a given handle point H and its associated
anchor point A is d, then it changes H to be a distances factor*d
away from A, but so that the line from A to H doesn't change.
This is mostly useful in the context of applying a (differentiable)
function, to preserve tangency properties. One would pull all the
handles closer to their anchors, apply the function then push them out
again.
"""
if self.get_num_points() == 0:
return
anchors, handles1, handles2 = self.get_anchors_and_handles()
# print len(anchors), len(handles1), len(handles2)
a_to_h1 = handles1 - anchors[:-1]
a_to_h2 = handles2 - anchors[1:]
handles1 = anchors[:-1] + factor*a_to_h1
handles2 = anchors[1:] + factor*a_to_h2
self.set_anchors_and_handles(anchors, handles1, handles2)
## Information about line
@ -272,7 +295,6 @@ class VMobject(Mobject):
## Alignment
def align_points(self, mobject):
Mobject.align_points(self, mobject)
is_subpath = self.is_subpath or mobject.is_subpath

View file

@ -114,7 +114,6 @@ class Sector(VMobject):
class Line(VMobject):
CONFIG = {
"buff" : 0,
"considered_smooth" : False,
"path_arc" : None,
"n_arc_anchors" : 10, #Only used if path_arc is not None
}
@ -132,7 +131,6 @@ class Line(VMobject):
path_func(self.start, self.end, alpha)
for alpha in np.linspace(0, 1, self.n_arc_anchors)
])
self.considered_smooth = True
self.account_for_buff()
def account_for_buff(self):
@ -449,7 +447,6 @@ class Polygon(VMobject):
"color" : GREEN_D,
"mark_paths_closed" : True,
"close_new_points" : True,
"considered_smooth" : False,
}
def __init__(self, *vertices, **kwargs):
assert len(vertices) > 1
@ -479,7 +476,6 @@ class Rectangle(VMobject):
"width" : 4.0,
"mark_paths_closed" : True,
"close_new_points" : True,
"considered_smooth" : False,
}
def generate_points(self):
y, x = self.height/2., self.width/2.
@ -586,7 +582,6 @@ class Grid(VMobject):
CONFIG = {
"height" : 6.0,
"width" : 6.0,
"considered_smooth" : False,
}
def __init__(self, rows, columns, **kwargs):
digest_config(self, kwargs, locals())

View file

@ -223,6 +223,7 @@ class NumberPlane(VMobject):
"secondary_line_ratio" : 1,
"written_coordinate_height" : 0.2,
"propagate_style_to_family" : False,
"make_smooth_after_applying_functions" : True,
}
def generate_points(self):
if self.x_radius is None:
@ -360,9 +361,6 @@ class NumberPlane(VMobject):
mob.make_smooth()
return self
def apply_function(self, function, maintain_smoothness = True):
VMobject.apply_function(self, function, maintain_smoothness = maintain_smoothness)

View file

@ -267,7 +267,6 @@ class VideoIcon(SVGMobject):
CONFIG = {
"file_name" : "video_icon",
"width" : 2*SPACE_WIDTH/12.,
"considered_smooth" : False,
}
def __init__(self, **kwargs):
SVGMobject.__init__(self, **kwargs)
@ -275,8 +274,6 @@ class VideoIcon(SVGMobject):
self.scale_to_fit_width(self.width)
self.set_stroke(color = WHITE, width = 0)
self.set_fill(color = WHITE, opacity = 1)
for mob in self:
mob.considered_smooth = False
class VideoSeries(VGroup):
CONFIG = {