Implmented ThreeDScene.add_fixed_orientation_mobjects and ThreeDScene.add_fixed_in_frame_mobjects

This commit is contained in:
Grant Sanderson 2018-08-22 14:48:42 -07:00
parent 0149f4a496
commit 7912f6f2d3
6 changed files with 86 additions and 20 deletions

View file

@ -341,7 +341,9 @@ class Camera(object):
def set_cairo_context_path(self, ctx, vmobject):
ctx.new_path()
for vmob in it.chain([vmobject], vmobject.get_subpath_mobjects()):
points = self.transform_points_pre_display(vmob.points)
points = self.transform_points_pre_display(
vmob, vmob.points
)
ctx.new_sub_path()
ctx.move_to(*points[0][:2])
for triplet in zip(points[1::3], points[2::3], points[3::3]):
@ -361,7 +363,9 @@ class Camera(object):
)
else:
points = vmobject.get_gradient_start_and_end_points()
points = self.transform_points_pre_display(points)
points = self.transform_points_pre_display(
vmobject, points
)
pat = cairo.LinearGradient(*it.chain(*[
point[:2] for point in points
]))
@ -420,16 +424,19 @@ class Camera(object):
def display_multiple_point_cloud_mobjects(self, pmobjects, pixel_array):
for pmobject in pmobjects:
self.display_point_cloud(
pmobject,
pmobject.points,
pmobject.rgbas,
self.adjusted_thickness(pmobject.stroke_width),
pixel_array,
)
def display_point_cloud(self, points, rgbas, thickness, pixel_array):
def display_point_cloud(self, pmobject, points, rgbas, thickness, pixel_array):
if len(points) == 0:
return
pixel_coords = self.points_to_pixel_coords(points)
pixel_coords = self.points_to_pixel_coords(
pmobject, points
)
pixel_coords = self.thickened_coordinates(
pixel_coords, thickness
)
@ -461,7 +468,9 @@ class Camera(object):
self.display_image_mobject(image_mobject, pixel_array)
def display_image_mobject(self, image_mobject, pixel_array):
corner_coords = self.points_to_pixel_coords(image_mobject.points)
corner_coords = self.points_to_pixel_coords(
image_mobject, image_mobject.points
)
ul_coords, ur_coords, dl_coords = corner_coords
right_vect = ur_coords - ul_coords
down_vect = dl_coords - ul_coords
@ -538,13 +547,15 @@ class Camera(object):
points[violator_indices] = rescaled
return points
def transform_points_pre_display(self, points):
def transform_points_pre_display(self, points, mobject):
# Subclasses (like ThreeDCamera) may want to
# adjust points before they're shown
return points
def points_to_pixel_coords(self, points):
points = self.transform_points_pre_display(points)
def points_to_pixel_coords(self, mobject, points):
points = self.transform_points_pre_display(
mobject, points
)
shifted_points = points - self.get_frame_center()
result = np.zeros((len(points), 2))

View file

@ -6,7 +6,6 @@ from constants import *
from camera.camera import Camera
from mobject.types.point_cloud_mobject import Point
from mobject.three_dimensions import ThreeDVMobject
from mobject.three_d_utils import get_3d_vmob_start_corner
from mobject.three_d_utils import get_3d_vmob_start_corner_unit_normal
from mobject.three_d_utils import get_3d_vmob_end_corner
@ -14,8 +13,10 @@ from mobject.three_d_utils import get_3d_vmob_end_corner_unit_normal
from mobject.value_tracker import ValueTracker
from utils.color import get_shaded_rgb
# from utils.config_ops import digest_config
from utils.space_ops import rotation_about_z
from utils.space_ops import rotation_matrix
from utils.space_ops import center_of_mass
class ThreeDCamera(Camera):
@ -40,6 +41,8 @@ class ThreeDCamera(Camera):
self.gamma_tracker = ValueTracker(self.gamma)
self.light_source = Point(self.light_source_start_point)
self.frame_center = Point(self.frame_center)
self.fixed_orientation_mobjects = set()
self.fixed_in_frame_mobjects = set()
self.reset_rotation_matrix()
def capture_mobjects(self, mobjects, **kwargs):
@ -155,15 +158,50 @@ class ThreeDCamera(Camera):
result = np.dot(matrix, result)
return result
def transform_points_pre_display(self, points):
fc = self.get_frame_center()
def project_points(self, points):
frame_center = self.get_frame_center()
distance = self.get_distance()
points -= fc
rot_matrix = self.get_rotation_matrix()
points -= frame_center
points = np.dot(points, rot_matrix.T)
zs = points[:, 2]
zs[zs >= distance] = distance - 0.001
for i in 0, 1:
points[:, i] *= distance / (distance - zs)
points += fc
points += frame_center
return points
def project_point(self, point):
return self.project_points(point.reshape((1, 3)))[0, :]
def transform_points_pre_display(self, mobject, points):
fixed_orientation = mobject in self.fixed_orientation_mobjects
fixed_in_frame = mobject in self.fixed_in_frame_mobjects
if fixed_in_frame:
return points
if fixed_orientation:
center = center_of_mass(points)
new_center = self.project_point(center)
return points + (new_center - center)
else:
return self.project_points(points)
def add_fixed_orientation_mobjects(self, *mobjects):
for mobject in self.extract_mobject_family_members(mobjects):
self.fixed_orientation_mobjects.add(mobject)
def add_fixed_in_frame_mobjects(self, *mobjects):
for mobject in self.extract_mobject_family_members(mobjects):
self.fixed_in_frame_mobjects.add(mobject)
def remove_fixed_orientation_mobjects(self, *mobjects):
for mobject in self.extract_mobject_family_members(mobjects):
if mobject in self.fixed_orientation_mobjects:
self.fixed_orientation_mobjects.remove(mobject)
def remove_fixed_in_frame_mobjects(self, *mobjects):
for mobject in self.extract_mobject_family_members(mobjects):
if mobject in self.fixed_in_frame_mobjects:
self.fixed_in_frame_mobjects.remove(mobject)

View file

@ -705,6 +705,8 @@ class Mobject(Container):
def get_critical_point(self, direction):
result = np.zeros(self.dim)
all_points = self.get_all_points()
if len(all_points) == 0:
return result
for dim in range(self.dim):
if direction[dim] <= 0:
min_val = min(all_points[:, dim])

View file

@ -96,16 +96,18 @@ class NumberLine(VMobject):
)
def point_to_number(self, point):
left_point, right_point = self.main_line.get_start_and_end()
full_vect = right_point - left_point
start_point, end_point = self.main_line.get_start_and_end()
full_vect = end_point - start_point
unit_vect = normalize(full_vect)
def distance_from_left(p):
return np.dot(p - left_point, full_vect) / get_norm(full_vect)
def distance_from_start(p):
return np.dot(p - start_point, unit_vect)
return interpolate(
self.x_min, self.x_max,
distance_from_left(point) / distance_from_left(right_point)
proportion = fdiv(
distance_from_start(point),
distance_from_start(end_point)
)
return interpolate(self.x_min, self.x_max, proportion)
def default_numbers_to_display(self):
if self.numbers_to_show is not None:

View file

@ -72,3 +72,15 @@ class ThreeDScene(Scene):
if any([cm in moving_mobjects for cm in camera_mobjects]):
return self.mobjects
return moving_mobjects
def add_fixed_orientation_mobjects(self, *mobjects):
self.camera.add_fixed_orientation_mobjects(*mobjects)
def add_fixed_in_frame_mobjects(self, *mobjects):
self.camera.add_fixed_in_frame_mobjects(*mobjects)
def remove_fixed_orientation_mobjects(self, *mobjects):
self.camera.remove_fixed_orientation_mobjects(*mobjects)
def remove_fixed_in_frame_mobjects(self, *mobjects):
self.camera.remove_fixed_in_frame_mobjects(*mobjects)

View file

@ -6,6 +6,7 @@ from functools import reduce
# Matrix operations
def get_norm(vect):
return sum([x**2 for x in vect])**0.5