Fixed align_to

This commit is contained in:
Grant Sanderson 2019-02-14 11:34:06 -08:00
parent f6d6958c2d
commit 4aa63198d7

View file

@ -411,31 +411,6 @@ class Mobject(Container):
buff * direction) * coor_mask)
return self
def align_to(self, mobject_or_point, direction=ORIGIN, alignment_vect=UP):
"""
Examples:
mob1.align_to(mob2, UP) moves mob1 vertically so that its
top edge lines ups with mob2's top edge.
mob1.align_to(mob2, alignment_vect = RIGHT) moves mob1
horizontally so that it's center is directly above/below
the center of mob2
"""
if isinstance(mobject_or_point, Mobject):
mob = mobject_or_point
target_point = mob.get_critical_point(direction)
else:
target_point = mobject_or_point
direction_norm = get_norm(direction)
if direction_norm > 0:
alignment_vect = np.array(direction) / direction_norm
reference_point = self.get_critical_point(direction)
else:
reference_point = self.get_center()
diff = target_point - reference_point
self.shift(alignment_vect * np.dot(diff, alignment_vect))
return self
def shift_onto_screen(self, **kwargs):
space_lengths = [FRAME_X_RADIUS, FRAME_Y_RADIUS]
for vect in UP, DOWN, LEFT, RIGHT:
@ -493,6 +468,22 @@ class Mobject(Container):
def set_depth(self, depth, stretch=False, **kwargs):
return self.rescale_to_fit(depth, 2, stretch=stretch, **kwargs)
def set_coord(self, value, dim, direction=ORIGIN):
curr = self.get_coord(dim, direction)
shift_vect = np.zeros(self.dim)
shift_vect[dim] = value - curr
self.shift(shift_vect)
return self
def set_x(self, x, direction=ORIGIN):
return self.set_coord(x, 0, direction)
def set_y(self, y, direction=ORIGIN):
return self.set_coord(y, 1, direction)
def set_z(self, z, direction=ORIGIN):
return self.set_coord(z, 2, direction)
def space_out_submobjects(self, factor=1.5, **kwargs):
self.scale(factor, **kwargs)
for submob in self.submobjects:
@ -534,17 +525,6 @@ class Mobject(Container):
self.scale_in_place((length + buff) / length)
return self
def get_start(self):
self.throw_error_if_no_points()
return np.array(self.points[0])
def get_end(self):
self.throw_error_if_no_points()
return np.array(self.points[-1])
def get_start_and_end(self):
return self.get_start(), self.get_end()
def put_start_and_end_on(self, start, end):
curr_start, curr_end = self.get_start_and_end()
curr_vect = curr_end - curr_start
@ -586,26 +566,6 @@ class Mobject(Container):
mob.add_background_rectangle(**kwargs)
return self
# Match other mobject properties
def match_color(self, mobject):
return self.set_color(mobject.get_color())
def match_dim(self, mobject, dim, **kwargs):
return self.rescale_to_fit(
mobject.length_over_dim(dim), dim,
**kwargs
)
def match_width(self, mobject, **kwargs):
return self.match_dim(mobject, 0, **kwargs)
def match_height(self, mobject, **kwargs):
return self.match_dim(mobject, 1, **kwargs)
def match_depth(self, mobject, **kwargs):
return self.match_dim(mobject, 2, **kwargs)
# Color functions
def set_color(self, color=YELLOW_C, family=True):
@ -735,23 +695,31 @@ class Mobject(Container):
def get_num_points(self):
return len(self.points)
def get_extremum_along_dim(self, points=None, dim=0, key=0):
if points is None:
points = self.get_points_defining_boundary()
values = points[:, dim]
if key < 0:
return np.min(values)
elif key == 0:
return (np.min(values) + np.max(values)) / 2
else:
return np.max(values)
def get_critical_point(self, direction):
"""
Picture a box bounding the mobject. Such a box has
9 'critical points': 4 corners, 4 edge center, the
center. This returns one of them.
"""
result = np.zeros(self.dim)
all_points = self.get_points_defining_boundary()
if len(all_points) == 0:
return result
for dim in range(self.dim):
if direction[dim] <= 0:
min_val = min(all_points[:, dim])
if direction[dim] >= 0:
max_val = max(all_points[:, dim])
if direction[dim] == 0:
result[dim] = (max_val + min_val) / 2
elif direction[dim] < 0:
result[dim] = min_val
else:
result[dim] = max_val
result[dim] = self.get_extremum_along_dim(
all_points, dim=dim, key=direction[dim]
)
return result
# Pseudonyms for more general get_critical_point method
@ -773,11 +741,6 @@ class Mobject(Container):
index = np.argmax(np.dot(all_points, np.array(direction).T))
return all_points[index]
def get_z_index_reference_point(self):
# TODO, better place to define default z_index_group?
z_index_group = getattr(self, "z_index_group", self)
return z_index_group.get_center()
def get_top(self):
return self.get_edge_center(UP)
@ -811,6 +774,34 @@ class Mobject(Container):
def get_depth(self):
return self.length_over_dim(2)
def get_coord(self, dim, direction=ORIGIN):
"""
Meant to generalize get_x, get_y, get_z
"""
return self.get_extremum_along_dim(
dim=dim, key=direction[dim]
)
def get_x(self, direction=ORIGIN):
return self.get_coord(0, direction)
def get_y(self, direction=ORIGIN):
return self.get_coord(1, direction)
def get_z(self, direction=ORIGIN):
return self.get_coord(2, direction)
def get_start(self):
self.throw_error_if_no_points()
return np.array(self.points[0])
def get_end(self):
self.throw_error_if_no_points()
return np.array(self.points[-1])
def get_start_and_end(self):
return self.get_start(), self.get_end()
def point_from_proportion(self, alpha):
raise Exception("Not implemented")
@ -825,12 +816,73 @@ class Mobject(Container):
for a1, a2 in zip(alphas[:-1], alphas[1:])
])
def get_z_index_reference_point(self):
# TODO, better place to define default z_index_group?
z_index_group = getattr(self, "z_index_group", self)
return z_index_group.get_center()
def has_points(self):
return len(self.points) > 0
def has_no_points(self):
return not self.has_points()
# Match other mobject properties
def match_color(self, mobject):
return self.set_color(mobject.get_color())
def match_dim_size(self, mobject, dim, **kwargs):
return self.rescale_to_fit(
mobject.length_over_dim(dim), dim,
**kwargs
)
def match_width(self, mobject, **kwargs):
return self.match_dim_size(mobject, 0, **kwargs)
def match_height(self, mobject, **kwargs):
return self.match_dim_size(mobject, 1, **kwargs)
def match_depth(self, mobject, **kwargs):
return self.match_dim_size(mobject, 2, **kwargs)
def match_coord(self, mobject, dim, direction=ORIGIN):
return self.set_coord(
mobject.get_coord(dim, direction),
dim=dim,
direction=direction,
)
def match_x(self, mobject, direction=ORIGIN):
return self.match_coord(mobject, 0, direction)
def match_y(self, mobject, direction=ORIGIN):
return self.match_coord(mobject, 1, direction)
def match_z(self, mobject, direction=ORIGIN):
return self.match_coord(mobject, 2, direction)
def align_to(self, mobject_or_point, direction=ORIGIN, alignment_vect=UP):
"""
Examples:
mob1.align_to(mob2, UP) moves mob1 vertically so that its
top edge lines ups with mob2's top edge.
mob1.align_to(mob2, alignment_vect = RIGHT) moves mob1
horizontally so that it's center is directly above/below
the center of mob2
"""
if isinstance(mobject_or_point, Mobject):
point = mobject_or_point.get_critical_point(direction)
else:
point = mobject_or_point
for dim in range(self.dim):
if direction[dim] != 0:
self.set_coord(point[dim], dim, direction)
return self
# Family matters
def __getitem__(self, value):