mirror of
https://github.com/3b1b/manim.git
synced 2025-08-05 16:49:03 +00:00
Merge pull request #80 from 3b1b/changes-implementation-of-basic-mobject-functions
Changes implementation of basic mobject functions
This commit is contained in:
commit
999a57a90b
3 changed files with 68 additions and 42 deletions
|
@ -143,7 +143,13 @@ class ApplyMethod(Transform):
|
|||
"the method you want to animate"
|
||||
)
|
||||
assert(isinstance(method.im_self, Mobject))
|
||||
method_kwargs = kwargs.get("method_kwargs", {})
|
||||
args = list(args) #So that args.pop() works
|
||||
if "method_kwargs" in kwargs:
|
||||
method_kwargs = kwargs["method_kwargs"]
|
||||
elif isinstance(args[-1], dict):
|
||||
method_kwargs = args.pop()
|
||||
else:
|
||||
method_kwargs = {}
|
||||
target = method.im_self.copy()
|
||||
method.im_func(target, *args, **method_kwargs)
|
||||
Transform.__init__(self, method.im_self, target, **kwargs)
|
||||
|
|
|
@ -138,7 +138,7 @@ class Mobject(object):
|
|||
mob.points += total_vector
|
||||
return self
|
||||
|
||||
def scale(self, scale_factor, about_point = None, about_edge = ORIGIN):
|
||||
def scale(self, scale_factor, **kwargs):
|
||||
"""
|
||||
Default behavior is to scale about the center of the mobject.
|
||||
The argument about_edge can be a vector, indicating which side of
|
||||
|
@ -148,46 +148,50 @@ class Mobject(object):
|
|||
Otherwise, if about_point is given a value, scaling is done with
|
||||
respect to that point.
|
||||
"""
|
||||
if about_point is None:
|
||||
about_point = self.get_critical_point(about_edge)
|
||||
self.shift(-about_point)
|
||||
for mob in self.family_members_with_points():
|
||||
mob.points *= scale_factor
|
||||
self.shift(about_point)
|
||||
self.apply_points_function_about_point(
|
||||
lambda points : scale_factor*points, **kwargs
|
||||
)
|
||||
return self
|
||||
|
||||
def rotate_about_origin(self, angle, axis = OUT, axes = []):
|
||||
if len(axes) == 0:
|
||||
axes = [axis]
|
||||
rot_matrix = np.identity(self.dim)
|
||||
for axis in axes:
|
||||
rot_matrix = np.dot(rot_matrix, rotation_matrix(angle, axis))
|
||||
t_rot_matrix = np.transpose(rot_matrix)
|
||||
for mob in self.family_members_with_points():
|
||||
mob.points = np.dot(mob.points, t_rot_matrix)
|
||||
return self.rotate(angle, axis, about_point = ORIGIN)
|
||||
|
||||
def rotate(self, angle, axis = OUT, **kwargs):
|
||||
rot_matrix = rotation_matrix(angle, axis)
|
||||
self.apply_points_function_about_point(
|
||||
lambda points : np.dot(points, rot_matrix.T),
|
||||
**kwargs
|
||||
)
|
||||
return self
|
||||
|
||||
def rotate(self, angle, axis = OUT, axes = [], about_point = None):
|
||||
if about_point is None:
|
||||
self.rotate_about_origin(angle, axis, axes)
|
||||
else:
|
||||
self.do_about_point(about_point, self.rotate, angle, axis, axes)
|
||||
def stretch(self, factor, dim, **kwargs):
|
||||
def func(points):
|
||||
points[:,dim] *= factor
|
||||
return points
|
||||
self.apply_points_function_about_point(func, **kwargs)
|
||||
return self
|
||||
|
||||
def stretch(self, factor, dim):
|
||||
for mob in self.family_members_with_points():
|
||||
mob.points[:,dim] *= factor
|
||||
def apply_function(self, function, **kwargs):
|
||||
#Default to applying matrix about the origin, not mobjects center
|
||||
if len(kwargs) == 0:
|
||||
kwargs["about_point"] = ORIGIN
|
||||
self.apply_points_function_about_point(
|
||||
lambda points : np.apply_along_axis(function, 1, points),
|
||||
about_point = about_point, **kwargs
|
||||
)
|
||||
return self
|
||||
|
||||
def apply_function(self, function):
|
||||
for mob in self.family_members_with_points():
|
||||
mob.points = np.apply_along_axis(function, 1, mob.points)
|
||||
return self
|
||||
|
||||
def apply_matrix(self, matrix):
|
||||
def apply_matrix(self, matrix, **kwargs):
|
||||
#Default to applying matrix about the origin, not mobjects center
|
||||
if len(kwargs) == 0:
|
||||
kwargs["about_point"] = ORIGIN
|
||||
full_matrix = np.identity(self.dim)
|
||||
matrix = np.array(matrix)
|
||||
for mob in self.family_members_with_points():
|
||||
mob.points = np.dot(mob.points, matrix.T)
|
||||
full_matrix[:matrix.shape[0],:matrix.shape[1]] = matrix
|
||||
self.apply_points_function_about_point(
|
||||
lambda points : np.dot(points, full_matrix.T),
|
||||
**kwargs
|
||||
)
|
||||
return self
|
||||
|
||||
def wag(self, direction = RIGHT, axis = DOWN, wag_factor = 1.0):
|
||||
|
@ -224,6 +228,15 @@ class Mobject(object):
|
|||
|
||||
#### In place operations ######
|
||||
|
||||
def apply_points_function_about_point(self, func, about_point = None, about_edge = ORIGIN):
|
||||
if about_point is None:
|
||||
about_point = self.get_critical_point(about_edge)
|
||||
for mob in self.family_members_with_points():
|
||||
mob.points -= about_point
|
||||
mob.points = func(mob.points)
|
||||
mob.points += about_point
|
||||
return self
|
||||
|
||||
def do_about_point(self, point, method, *args, **kwargs):
|
||||
self.shift(-point)
|
||||
method(*args, **kwargs)
|
||||
|
@ -235,8 +248,8 @@ class Mobject(object):
|
|||
return self
|
||||
|
||||
def rotate_in_place(self, angle, axis = OUT, axes = []):
|
||||
self.do_in_place(self.rotate, angle, axis, axes)
|
||||
return self
|
||||
# redundant with default behavior of rotate now.
|
||||
return self.rotate(angle, axis = axis, axes = axes)
|
||||
|
||||
def flip(self, axis = UP):
|
||||
self.rotate_in_place(np.pi, axis)
|
||||
|
@ -244,12 +257,11 @@ class Mobject(object):
|
|||
|
||||
def scale_in_place(self, scale_factor):
|
||||
#Redundant with default behavior of scale now.
|
||||
self.do_in_place(self.scale, scale_factor)
|
||||
return self
|
||||
return self.scale(scale_factor)
|
||||
|
||||
def scale_about_point(self, scale_factor, point):
|
||||
self.do_about_point(point, self.scale, scale_factor)
|
||||
return self
|
||||
#Redundant with default behavior of scale now.
|
||||
return self.scale(scale_factor, about_point = point)
|
||||
|
||||
def pose_at_angle(self):
|
||||
self.rotate_in_place(np.pi / 7, RIGHT+UP)
|
||||
|
|
|
@ -340,8 +340,9 @@ class Scene(object):
|
|||
|
||||
def compile_play_args_to_animation_list(self, *args):
|
||||
"""
|
||||
Eacn arg can either be an animation, or a mobject method
|
||||
followed by that methods arguments.
|
||||
Each arg can either be an animation, or a mobject method
|
||||
followed by that methods arguments (and potentially follow
|
||||
by a dict of kwargs for that method).
|
||||
|
||||
This animation list is built by going through the args list,
|
||||
and each animation is simply added, but when a mobject method
|
||||
|
@ -364,8 +365,15 @@ class Scene(object):
|
|||
#method should already have target then.
|
||||
else:
|
||||
mobject.target = mobject.copy()
|
||||
#
|
||||
if isinstance(state["method_args"][-1], dict):
|
||||
method_kwargs = state["method_args"].pop()
|
||||
else:
|
||||
method_kwargs = {}
|
||||
state["curr_method"].im_func(
|
||||
mobject.target, *state["method_args"]
|
||||
mobject.target,
|
||||
*state["method_args"],
|
||||
**method_kwargs
|
||||
)
|
||||
animations.append(MoveToTarget(mobject))
|
||||
state["last_method"] = state["curr_method"]
|
||||
|
|
Loading…
Add table
Reference in a new issue