mirror of
https://github.com/3b1b/manim.git
synced 2026-04-26 03:00:23 -04:00
Merge pull request #271 from 3b1b/simple-improvements
Simple improvements
This commit is contained in:
@@ -49,7 +49,6 @@ class Camera(object):
|
||||
"image_mode": "RGBA",
|
||||
"n_channels": 4,
|
||||
"pixel_array_dtype": 'uint8',
|
||||
"use_z_coordinate_for_display_order": False,
|
||||
# z_buff_func is only used if the flag above is set to True.
|
||||
# round z coordinate to nearest hundredth when comparring
|
||||
"z_buff_func": lambda m: np.round(m.get_center()[2], 2),
|
||||
@@ -231,16 +230,7 @@ class Camera(object):
|
||||
excluded_mobjects
|
||||
)
|
||||
mobjects = list_difference_update(mobjects, all_excluded)
|
||||
if self.use_z_coordinate_for_display_order:
|
||||
# Should perhaps think about what happens here when include_submobjects is False,
|
||||
# (for now, the onus is then on the caller to ensure this is handled correctly by
|
||||
# passing us an appropriately pre-flattened list of mobjects if need be)
|
||||
return sorted(
|
||||
mobjects,
|
||||
lambda a, b: cmp(self.z_buff_func(a), self.z_buff_func(b))
|
||||
)
|
||||
else:
|
||||
return mobjects
|
||||
return mobjects
|
||||
|
||||
def is_in_frame(self, mobject):
|
||||
fc = self.get_frame_center()
|
||||
|
||||
@@ -11,6 +11,7 @@ from mobject.number_line import NumberLine
|
||||
from mobject.svg.tex_mobject import TexMobject
|
||||
from mobject.types.vectorized_mobject import VGroup
|
||||
from mobject.types.vectorized_mobject import VMobject
|
||||
from mobject.three_dimensions import ThreeDVMobject
|
||||
from utils.config_ops import digest_config
|
||||
from utils.space_ops import angle_of_vector
|
||||
|
||||
@@ -29,14 +30,10 @@ class Axes(VGroup):
|
||||
"y_axis_config": {
|
||||
"label_direction": LEFT,
|
||||
},
|
||||
"z_axis_config": {},
|
||||
"x_min": -FRAME_X_RADIUS,
|
||||
"x_max": FRAME_X_RADIUS,
|
||||
"y_min": -FRAME_Y_RADIUS,
|
||||
"y_max": FRAME_Y_RADIUS,
|
||||
"z_min": -3.5,
|
||||
"z_max": 3.5,
|
||||
"z_normal": DOWN,
|
||||
"default_num_graph_points": 100,
|
||||
}
|
||||
|
||||
@@ -46,15 +43,6 @@ class Axes(VGroup):
|
||||
self.y_axis = self.get_axis(self.y_min, self.y_max, self.y_axis_config)
|
||||
self.y_axis.rotate(np.pi / 2, about_point=ORIGIN)
|
||||
self.add(self.x_axis, self.y_axis)
|
||||
if self.three_d:
|
||||
self.z_axis = self.get_axis(
|
||||
self.z_min, self.z_max, self.z_axis_config)
|
||||
self.z_axis.rotate(-np.pi / 2, UP, about_point=ORIGIN)
|
||||
self.z_axis.rotate(
|
||||
angle_of_vector(self.z_normal), OUT,
|
||||
about_point=ORIGIN
|
||||
)
|
||||
self.add(self.z_axis)
|
||||
|
||||
def get_axis(self, min_val, max_val, extra_config):
|
||||
config = dict(self.number_line_config)
|
||||
@@ -68,10 +56,10 @@ class Axes(VGroup):
|
||||
return x_axis_projection + y_axis_projection - origin
|
||||
|
||||
def point_to_coords(self, point):
|
||||
return (
|
||||
self.x_axis.point_to_number(point),
|
||||
self.y_axis.point_to_number(point),
|
||||
)
|
||||
return tuple([
|
||||
axis.point_to_number(point)
|
||||
for axis in self
|
||||
])
|
||||
|
||||
def get_graph(
|
||||
self, function, num_graph_points=None,
|
||||
@@ -123,11 +111,56 @@ class ThreeDAxes(Axes):
|
||||
CONFIG = {
|
||||
"x_min": -5.5,
|
||||
"x_max": 5.5,
|
||||
"y_min": -4.5,
|
||||
"y_max": 4.5,
|
||||
"three_d": True,
|
||||
"y_min": -5.5,
|
||||
"y_max": 5.5,
|
||||
"z_axis_config": {},
|
||||
"z_min": -3.5,
|
||||
"z_max": 3.5,
|
||||
"z_normal": DOWN,
|
||||
"num_axis_pieces": 20,
|
||||
"light_source": 9 * DOWN + 7 * LEFT + 10 * OUT,
|
||||
}
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
Axes.__init__(self, **kwargs)
|
||||
z_axis = self.z_axis = self.get_axis(
|
||||
self.z_min, self.z_max, self.z_axis_config
|
||||
)
|
||||
z_axis.rotate(-np.pi / 2, UP, about_point=ORIGIN)
|
||||
z_axis.rotate(
|
||||
angle_of_vector(self.z_normal), OUT,
|
||||
about_point=ORIGIN
|
||||
)
|
||||
self.add(z_axis)
|
||||
|
||||
self.add_3d_pieces()
|
||||
self.set_axis_shading()
|
||||
|
||||
def add_3d_pieces(self):
|
||||
for attr in "x_axis", "y_axis", "z_axis":
|
||||
axis = getattr(self, attr)
|
||||
axis.add(VGroup(
|
||||
*axis.main_line.get_pieces(self.num_axis_pieces)
|
||||
))
|
||||
axis.main_line.set_stroke(width=0, family=False)
|
||||
axis_3d = ThreeDVMobject(axis)
|
||||
self.remove(axis)
|
||||
self.add(axis_3d)
|
||||
setattr(self, attr, axis_3d)
|
||||
|
||||
def set_axis_shading(self):
|
||||
def make_func(axis):
|
||||
vect = self.light_source
|
||||
return lambda: (
|
||||
axis.get_edge_center(-vect),
|
||||
axis.get_edge_center(vect),
|
||||
)
|
||||
for axis in self:
|
||||
for submob in axis.family_members_with_points():
|
||||
submob.get_gradient_start_and_end_points = make_func(axis)
|
||||
submob.get_unit_normal = lambda a: np.ones(3)
|
||||
submob.set_sheen(0.2)
|
||||
|
||||
|
||||
class NumberPlane(VMobject):
|
||||
CONFIG = {
|
||||
|
||||
@@ -47,14 +47,14 @@ class Mobject(Container):
|
||||
if self.name is None:
|
||||
self.name = self.__class__.__name__
|
||||
self.updaters = []
|
||||
self.init_points()
|
||||
self.reset_points()
|
||||
self.generate_points()
|
||||
self.init_colors()
|
||||
|
||||
def __str__(self):
|
||||
return str(self.name)
|
||||
|
||||
def init_points(self):
|
||||
def reset_points(self):
|
||||
self.points = np.zeros((0, self.dim))
|
||||
|
||||
def init_colors(self):
|
||||
@@ -773,6 +773,17 @@ class Mobject(Container):
|
||||
def point_from_proportion(self, alpha):
|
||||
raise Exception("Not implemented")
|
||||
|
||||
def get_pieces(self, n_pieces):
|
||||
template = self.copy()
|
||||
template.submobjects = []
|
||||
alphas = np.linspace(0, 1, n_pieces + 1)
|
||||
return Group(*[
|
||||
template.copy().pointwise_become_partial(
|
||||
self, a1, a2
|
||||
)
|
||||
for a1, a2 in zip(alphas[:-1], alphas[1:])
|
||||
])
|
||||
|
||||
# Family matters
|
||||
|
||||
def __getitem__(self, value):
|
||||
@@ -909,7 +920,7 @@ class Mobject(Container):
|
||||
def push_self_into_submobjects(self):
|
||||
copy = self.copy()
|
||||
copy.submobjects = []
|
||||
self.init_points()
|
||||
self.reset_points()
|
||||
self.add(copy)
|
||||
return self
|
||||
|
||||
|
||||
@@ -145,6 +145,7 @@ class NumberLine(VMobject):
|
||||
vect = (end - start) / get_norm(end - start)
|
||||
arrow = Arrow(start, end + MED_SMALL_BUFF * vect, buff=0)
|
||||
tip = arrow.tip
|
||||
tip.set_stroke(width=self.get_stroke_width())
|
||||
tip.set_color(self.color)
|
||||
self.tip = tip
|
||||
self.add(tip)
|
||||
|
||||
@@ -21,10 +21,11 @@ class ThreeDVMobject(VMobject):
|
||||
VMobject.__init__(self, **kwargs)
|
||||
if vmobject is not None:
|
||||
self.points = np.array(vmobject.points)
|
||||
self.match_style(vmobject)
|
||||
self.submobjects = map(
|
||||
ThreeDVMobject, vmobject.submobjects
|
||||
)
|
||||
self.match_style(vmobject, family=False)
|
||||
self.submobjects = [
|
||||
ThreeDVMobject(submob, **kwargs)
|
||||
for submob in vmobject.submobjects
|
||||
]
|
||||
|
||||
def get_gradient_start_and_end_points(self):
|
||||
return self.get_start_corner(), self.get_end_corner()
|
||||
|
||||
@@ -30,7 +30,7 @@ class AbstractImageMobject(Mobject):
|
||||
# Likely to be implemented in subclasses, but no obgligation
|
||||
pass
|
||||
|
||||
def init_points(self):
|
||||
def reset_points(self):
|
||||
# Corresponding corners of image are fixed to these 3 points
|
||||
self.points = np.array([
|
||||
UP + LEFT,
|
||||
|
||||
@@ -17,7 +17,7 @@ class PMobject(Mobject):
|
||||
"stroke_width": DEFAULT_STROKE_WIDTH,
|
||||
}
|
||||
|
||||
def init_points(self):
|
||||
def reset_points(self):
|
||||
self.rgbas = np.zeros((0, 4))
|
||||
self.points = np.zeros((0, 3))
|
||||
return self
|
||||
|
||||
@@ -158,21 +158,22 @@ class VMobject(Mobject):
|
||||
self.set_stroke(color, family=family)
|
||||
return self
|
||||
|
||||
def match_style(self, vmobject):
|
||||
def match_style(self, vmobject, family=True):
|
||||
for a_name in ["fill_rgbas", "stroke_rgbas", "background_stroke_rgbas"]:
|
||||
setattr(self, a_name, np.array(getattr(vmobject, a_name)))
|
||||
self.stroke_width = vmobject.stroke_width
|
||||
self.background_stroke_width = vmobject.background_stroke_width
|
||||
|
||||
# Does its best to match up submobject lists, and
|
||||
# match styles accordingly
|
||||
submobs1, submobs2 = self.submobjects, vmobject.submobjects
|
||||
if len(submobs1) == 0:
|
||||
return self
|
||||
elif len(submobs2) == 0:
|
||||
submobs2 = [vmobject]
|
||||
for sm1, sm2 in zip(*make_even(submobs1, submobs2)):
|
||||
sm1.match_style(sm2)
|
||||
if family:
|
||||
# Does its best to match up submobject lists, and
|
||||
# match styles accordingly
|
||||
submobs1, submobs2 = self.submobjects, vmobject.submobjects
|
||||
if len(submobs1) == 0:
|
||||
return self
|
||||
elif len(submobs2) == 0:
|
||||
submobs2 = [vmobject]
|
||||
for sm1, sm2 in zip(*make_even(submobs1, submobs2)):
|
||||
sm1.match_style(sm2)
|
||||
return self
|
||||
|
||||
def fade_no_recurse(self, darkness):
|
||||
|
||||
@@ -144,7 +144,7 @@ class Vibrate(Animation):
|
||||
Animation.__init__(self, Mobject1D(color = self.color), **kwargs)
|
||||
|
||||
def update_mobject(self, alpha):
|
||||
self.mobject.init_points()
|
||||
self.mobject.reset_points()
|
||||
epsilon = self.mobject.epsilon
|
||||
self.mobject.add_points([
|
||||
[x*self.radius, self.func(x, alpha*self.run_time)+y, 0]
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import itertools as it
|
||||
import numpy as np
|
||||
from functools import reduce
|
||||
|
||||
|
||||
def remove_list_redundancies(l):
|
||||
@@ -108,6 +107,7 @@ def make_even_by_cycling(iterable_1, iterable_2):
|
||||
def remove_nones(sequence):
|
||||
return [x for x in sequence if x]
|
||||
|
||||
|
||||
# Note this is redundant with it.chain
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user