resolve conflict

This commit is contained in:
TonyCrane 2022-02-14 14:12:06 +08:00
commit a0ed9edb42
No known key found for this signature in database
GPG key ID: 2313A5058A9C637C
17 changed files with 134 additions and 60 deletions

View file

@ -1,7 +1,6 @@
from manimlib.animation.animation import Animation
from manimlib.animation.composition import Succession
from manimlib.mobject.types.vectorized_mobject import VMobject
from manimlib.mobject.mobject import Group
from manimlib.utils.bezier import integer_interpolate
from manimlib.utils.config_ops import digest_config
from manimlib.utils.rate_functions import linear
@ -147,7 +146,7 @@ class Write(DrawBorderThenFill):
else:
self.run_time = 2
if self.lag_ratio is None:
self.lag_ratio = min(4.0 / length, 0.2)
self.lag_ratio = min(4.0 / (length + 1.0), 0.2)
class ShowIncreasingSubsets(Animation):

View file

@ -17,7 +17,6 @@ class Broadcast(LaggedStart):
"remover": True,
"lag_ratio": 0.2,
"run_time": 3,
"remover": True,
}
def __init__(self, focal_point, **kwargs):

View file

@ -65,6 +65,12 @@ def parse_cli():
action="store_true",
help="Show window in full screen",
)
parser.add_argument(
"-p", "--presenter_mode",
action="store_true",
help="scene will stay paused during wait calls until "
"space bar or right arrow is hit, like a slide show"
)
parser.add_argument(
"-g", "--save_pngs",
action="store_true",
@ -306,6 +312,7 @@ def get_configuration(args):
"start_at_animation_number": args.start_at_animation_number,
"end_at_animation_number": None,
"preview": not write_file,
"presenter_mode": args.presenter_mode,
"leave_progress_bars": args.leave_progress_bars,
}

View file

@ -64,6 +64,7 @@ def get_scene_config(config):
"end_at_animation_number",
"leave_progress_bars",
"preview",
"presenter_mode",
]
])

View file

@ -277,7 +277,7 @@ class CoordinateSystem():
class Axes(VGroup, CoordinateSystem):
CONFIG = {
"axis_config": {
"include_tip": True,
"include_tip": False,
"numbers_to_exclude": [0],
},
"x_axis_config": {},

View file

@ -44,6 +44,8 @@ class ParametricCurve(VMobject):
self.add_points_as_corners(points[1:])
if self.use_smoothing:
self.make_approximately_smooth()
if not self.has_points():
self.set_points([self.t_func(t_min)])
return self

View file

@ -112,7 +112,7 @@ class Matrix(VMobject):
"\\left[",
"\\begin{array}{c}",
*height * ["\\quad \\\\"],
"\\end{array}"
"\\end{array}",
"\\right]",
]))[0]
bracket_pair.set_height(

View file

@ -899,6 +899,21 @@ class Mobject(object):
self.set_depth(max_depth, **kwargs)
return self
def set_min_width(self, min_width: float, **kwargs):
if self.get_width() < min_width:
self.set_width(min_width, **kwargs)
return self
def set_min_height(self, min_height: float, **kwargs):
if self.get_height() < min_height:
self.set_height(min_height, **kwargs)
return self
def set_min_depth(self, min_depth: float, **kwargs):
if self.get_depth() < min_depth:
self.set_depth(min_depth, **kwargs)
return self
def set_coord(self, value: float, dim: int, direction: np.ndarray = ORIGIN):
curr = self.get_coord(dim, direction)
shift_vect = np.zeros(self.dim)
@ -1295,21 +1310,38 @@ class Mobject(object):
def match_depth(self, mobject: "Mobject", **kwargs):
return self.match_dim_size(mobject, 2, **kwargs)
def match_coord(self, mobject: "Mobject", dim: int, direction: np.ndarray = ORIGIN):
return self.set_coord(
mobject.get_coord(dim, direction),
dim=dim,
direction=direction,
)
def match_coord(
self,
mobject_or_point: "Mobject" | np.ndarray,
dim: int,
direction: np.ndarray = ORIGIN
):
if isinstance(mobject_or_point, Mobject):
coord = mobject_or_point.get_coord(dim, direction)
else:
coord = mobject_or_point[dim]
return self.set_coord(coord, dim=dim, direction=direction)
def match_x(self, mobject: "Mobject", direction: np.ndarray = ORIGIN):
return self.match_coord(mobject, 0, direction)
def match_x(
self,
mobject_or_point: "Mobject" | np.ndarray,
direction: np.ndarray = ORIGIN
):
return self.match_coord(mobject_or_point, 0, direction)
def match_y(self, mobject: "Mobject", direction: np.ndarray = ORIGIN):
return self.match_coord(mobject, 1, direction)
def match_y(
self,
mobject_or_point: "Mobject" | np.ndarray,
direction: np.ndarray = ORIGIN
):
return self.match_coord(mobject_or_point, 1, direction)
def match_z(self, mobject: "Mobject", direction: np.ndarray = ORIGIN):
return self.match_coord(mobject, 2, direction)
def match_z(
self,
mobject_or_point: "Mobject" | np.ndarray,
direction: np.ndarray = ORIGIN
):
return self.match_coord(mobject_or_point, 2, direction)
def align_to(
self,

View file

@ -318,6 +318,9 @@ class Bubble(SVGMobject):
self.content = Mobject()
self.refresh_triangulation()
def init_colors(self):
VMobject.init_colors(self)
def get_tip(self):
# TODO, find a better way
return self.get_corner(DOWN + self.direction) - 0.6 * self.direction

View file

@ -13,7 +13,6 @@ from manimlib.mobject.geometry import Polygon
from manimlib.mobject.geometry import Polyline
from manimlib.mobject.geometry import Rectangle
from manimlib.mobject.geometry import RoundedRectangle
from manimlib.mobject.types.vectorized_mobject import VGroup
from manimlib.mobject.types.vectorized_mobject import VMobject
from manimlib.utils.config_ops import digest_config
from manimlib.utils.directories import get_mobject_data_dir
@ -321,4 +320,4 @@ class VMobjectFromSVGPath(VMobject):
_convert_point_to_3d(*segment.__getattribute__(attr_name))
for attr_name in attr_names
]
func(*points)
func(*points)

View file

@ -36,20 +36,19 @@ class SingleStringTex(VMobject):
assert(isinstance(tex_string, str))
self.tex_string = tex_string
if tex_string not in tex_string_with_color_to_mob_map:
with display_during_execution(f" Writing \"{tex_string}\""):
full_tex = self.get_tex_file_body(tex_string)
filename = tex_to_svg_file(full_tex)
svg_mob = SVGMobject(
filename,
height=None,
color=self.color,
stroke_width=self.stroke_width,
path_string_config={
"should_subdivide_sharp_curves": True,
"should_remove_null_curves": True,
}
)
tex_string_with_color_to_mob_map[(self.color, tex_string)] = svg_mob
full_tex = self.get_tex_file_body(tex_string)
filename = tex_to_svg_file(full_tex)
svg_mob = SVGMobject(
filename,
height=None,
color=self.color,
stroke_width=self.stroke_width,
path_string_config={
"should_subdivide_sharp_curves": True,
"should_remove_null_curves": True,
}
)
tex_string_with_color_to_mob_map[(self.color, tex_string)] = svg_mob
self.add(*(
sm.copy()
for sm in tex_string_with_color_to_mob_map[(self.color, tex_string)]
@ -140,7 +139,11 @@ class SingleStringTex(VMobject):
Makes Tex resiliant to unmatched braces
"""
num_unclosed_brackets = 0
for char in tex:
for i in range(len(tex)):
if i > 0 and tex[i - 1] == "\\":
# So as to not count '\{' type expressions
continue
char = tex[i]
if char == "{":
num_unclosed_brackets += 1
elif char == "}":

View file

@ -35,6 +35,8 @@ class PMobject(Mobject):
return self
def set_points(self, points: npt.ArrayLike):
if len(points) == 0:
points = np.zeros((0, 3))
super().set_points(points)
self.resize_points(len(points))
return self
@ -54,14 +56,18 @@ class PMobject(Mobject):
if color is not None:
if opacity is None:
opacity = self.data["rgbas"][-1, 3]
new_rgbas = np.repeat(
rgbas = np.repeat(
[color_to_rgba(color, opacity)],
len(points),
axis=0
)
elif rgbas is not None:
new_rgbas = rgbas
self.data["rgbas"][-len(new_rgbas):] = new_rgbas
if rgbas is not None:
self.data["rgbas"][-len(rgbas):] = rgbas
return self
def add_point(self, point, rgba=None, color=None, opacity=None):
rgbas = None if rgba is None else [rgba]
self.add_points([point], rgbas, color, opacity)
return self
def set_color_by_gradient(self, *colors: ManimColor):

View file

@ -277,7 +277,6 @@ class DiscreteGraphScene(Scene):
def trace_cycle(self, cycle=None, color="yellow", run_time=2.0):
if cycle is None:
cycle = self.graph.region_cycles[0]
time_per_edge = run_time / len(cycle)
next_in_cycle = it.cycle(cycle)
next(next_in_cycle) # jump one ahead
self.traced_cycle = Mobject(*[

View file

@ -36,6 +36,7 @@ class Scene(object):
"end_at_animation_number": None,
"leave_progress_bars": False,
"preview": True,
"presenter_mode": False,
"linger_after_completion": True,
}
@ -62,6 +63,7 @@ class Scene(object):
# Items associated with interaction
self.mouse_point = Point()
self.mouse_drag_point = Point()
self.hold_on_wait = not self.presenter_mode
# Much nicer to work with deterministic scenes
if self.random_seed is not None:
@ -114,7 +116,7 @@ class Scene(object):
if self.quit_interaction:
self.unlock_mobject_data()
def embed(self):
def embed(self, close_scene_on_exit=True):
if not self.preview:
# If the scene is just being
# written, ignore embed calls
@ -139,8 +141,9 @@ class Scene(object):
log.info("Tips: Now the embed iPython terminal is open. But you can't interact with"
" the window directly. To do so, you need to type `touch()` or `self.interact()`")
shell(local_ns=local_ns, stack_depth=2)
# End scene when exiting an embed.
raise EndSceneEarlyException()
# End scene when exiting an embed
if close_scene_on_exit:
raise EndSceneEarlyException()
def __str__(self):
return self.__class__.__name__
@ -432,6 +435,11 @@ class Scene(object):
def unlock_mobject_data(self):
self.camera.release_static_mobjects()
def refresh_locked_data(self):
self.unlock_mobject_data()
self.lock_static_mobject_data()
return self
def begin_animations(self, animations):
for animation in animations:
animation.begin()
@ -477,19 +485,30 @@ class Scene(object):
self.unlock_mobject_data()
@handle_play_like_call
def wait(self, duration=DEFAULT_WAIT_TIME, stop_condition=None):
def wait(self,
duration=DEFAULT_WAIT_TIME,
stop_condition=None,
note=None,
ignore_presenter_mode=False):
if note:
log.info(note)
self.update_mobjects(dt=0) # Any problems with this?
self.lock_static_mobject_data()
time_progression = self.get_wait_time_progression(duration, stop_condition)
last_t = 0
for t in time_progression:
dt = t - last_t
last_t = t
self.update_frame(dt)
self.emit_frame()
if stop_condition is not None and stop_condition():
time_progression.close()
break
if self.presenter_mode and not self.skip_animations and not ignore_presenter_mode:
while self.hold_on_wait:
self.update_frame(dt=1 / self.camera.frame_rate)
self.hold_on_wait = True
else:
time_progression = self.get_wait_time_progression(duration, stop_condition)
last_t = 0
for t in time_progression:
dt = t - last_t
last_t = t
self.update_frame(dt)
self.emit_frame()
if stop_condition is not None and stop_condition():
time_progression.close()
break
self.unlock_mobject_data()
return self
@ -610,6 +629,10 @@ class Scene(object):
self.camera.frame.to_default_state()
elif char == "q":
self.quit_interaction = True
elif char == " ":
self.hold_on_wait = False
elif char == "e":
self.embed(close_scene_on_exit=False)
def on_resize(self, width: int, height: int):
self.camera.reset_pixel_shape(width, height)

View file

@ -287,9 +287,6 @@ class LinearTransformationScene(VectorScene):
},
"background_plane_kwargs": {
"color": GREY,
"axis_config": {
"stroke_color": GREY_B,
},
"axis_config": {
"color": GREY,
},

View file

@ -21,10 +21,10 @@ def bezier(
n = len(points) - 1
def result(t):
return sum([
return sum(
((1 - t)**(n - k)) * (t**k) * choose(n, k) * point
for k, point in enumerate(points)
])
)
return result

View file

@ -1,6 +1,6 @@
import inspect
import numpy as np
from scipy import special
import math
from functools import lru_cache
@ -10,7 +10,11 @@ def sigmoid(x):
@lru_cache(maxsize=10)
def choose(n, k):
return special.comb(n, k, exact=True)
return math.comb(n, k)
def gen_choose(n, r):
return np.prod(np.arange(n, n - r, -1)) / math.factorial(r)
def get_num_args(function):