mirror of
https://github.com/3b1b/manim.git
synced 2025-08-05 16:49:03 +00:00
Merge pull request #1952 from 3b1b/video-work
More miscellaneous tweaks and fixes
This commit is contained in:
commit
124c83d94e
13 changed files with 291 additions and 302 deletions
|
@ -29,6 +29,7 @@ class AnimationGroup(Animation):
|
|||
run_time: float = -1, # If negative, default to sum of inputed animation runtimes
|
||||
lag_ratio: float = 0.0,
|
||||
group: Mobject | None = None,
|
||||
group_type: type = Group,
|
||||
**kwargs
|
||||
):
|
||||
self.animations = [prepare_animation(anim) for anim in animations]
|
||||
|
@ -38,7 +39,7 @@ class AnimationGroup(Animation):
|
|||
self.lag_ratio = lag_ratio
|
||||
self.group = group
|
||||
if self.group is None:
|
||||
self.group = Group(*remove_list_redundancies(
|
||||
self.group = group_type(*remove_list_redundancies(
|
||||
[anim.mobject for anim in self.animations]
|
||||
))
|
||||
|
||||
|
@ -49,7 +50,7 @@ class AnimationGroup(Animation):
|
|||
**kwargs
|
||||
)
|
||||
|
||||
def get_all_mobjects(self) -> Group:
|
||||
def get_all_mobjects(self) -> Mobject:
|
||||
return self.group
|
||||
|
||||
def begin(self) -> None:
|
||||
|
|
|
@ -4,26 +4,20 @@ import itertools as it
|
|||
|
||||
import numpy as np
|
||||
|
||||
from manimlib.animation.animation import Animation
|
||||
from manimlib.animation.composition import AnimationGroup
|
||||
from manimlib.animation.fading import FadeInFromPoint
|
||||
from manimlib.animation.fading import FadeOutToPoint
|
||||
from manimlib.animation.fading import FadeTransformPieces
|
||||
from manimlib.animation.fading import FadeTransform
|
||||
from manimlib.animation.transform import ReplacementTransform
|
||||
from manimlib.animation.transform import Transform
|
||||
from manimlib.mobject.mobject import Mobject
|
||||
from manimlib.mobject.mobject import Group
|
||||
from manimlib.mobject.svg.string_mobject import StringMobject
|
||||
from manimlib.mobject.svg.old_tex_mobject import OldTex
|
||||
from manimlib.mobject.svg.tex_mobject import Tex
|
||||
from manimlib.mobject.types.vectorized_mobject import VGroup
|
||||
from manimlib.mobject.types.vectorized_mobject import VMobject
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from manimlib.mobject.svg.old_tex_mobject import SingleStringTex
|
||||
from manimlib.scene.scene import Scene
|
||||
|
||||
|
||||
|
@ -151,13 +145,14 @@ class TransformMatchingStrings(AnimationGroup):
|
|||
match_animation: type = Transform,
|
||||
mismatch_animation: type = Transform,
|
||||
run_time=2,
|
||||
lag_ratio=0,
|
||||
**kwargs,
|
||||
):
|
||||
self.source = source
|
||||
self.target = target
|
||||
matched_keys = matched_keys or list()
|
||||
key_map = key_map or dict()
|
||||
self.anim_config = dict(run_time=run_time, **kwargs)
|
||||
self.anim_config = dict(**kwargs)
|
||||
|
||||
# We will progressively build up a list of transforms
|
||||
# from characters in source to those in target. These
|
||||
|
@ -208,7 +203,12 @@ class TransformMatchingStrings(AnimationGroup):
|
|||
target_char, source.get_center(),
|
||||
**self.anim_config
|
||||
))
|
||||
super().__init__(*self.anims)
|
||||
super().__init__(
|
||||
*self.anims,
|
||||
run_time=run_time,
|
||||
lag_ratio=lag_ratio,
|
||||
group_type=VGroup,
|
||||
)
|
||||
|
||||
def add_transform(
|
||||
self,
|
||||
|
@ -230,18 +230,10 @@ class TransformMatchingStrings(AnimationGroup):
|
|||
self.target_chars.remove(char)
|
||||
|
||||
def find_pairs_with_matching_shapes(self, chars1, chars2) -> list[tuple[VMobject, VMobject]]:
|
||||
for char in (*chars1, *chars2):
|
||||
char.save_state()
|
||||
char.set_height(1)
|
||||
char.center()
|
||||
result = []
|
||||
for char1, char2 in it.product(chars1, chars2):
|
||||
p1 = char1.get_points()
|
||||
p2 = char2.get_points()
|
||||
if len(p1) == len(p2) and np.isclose(p1, p2 , atol=1e-1).all():
|
||||
if char1.has_same_shape_as(char2):
|
||||
result.append((char1, char2))
|
||||
for char in (*chars1, *chars2):
|
||||
char.restore()
|
||||
return result
|
||||
|
||||
def clean_up_from_scene(self, scene: Scene) -> None:
|
||||
|
|
|
@ -491,4 +491,6 @@ def get_configuration(args: Namespace) -> dict:
|
|||
"presenter_mode": args.presenter_mode,
|
||||
"leave_progress_bars": args.leave_progress_bars,
|
||||
"show_animation_progress": args.show_animation_progress,
|
||||
"embed_exception_mode": custom_config["embed_exception_mode"],
|
||||
"embed_error_sound": custom_config["embed_error_sound"],
|
||||
}
|
||||
|
|
|
@ -42,3 +42,5 @@ camera_resolutions:
|
|||
4k: "3840x2160"
|
||||
default_resolution: "high"
|
||||
fps: 30
|
||||
embed_exception_mode: "Verbose"
|
||||
embed_error_sound: False
|
||||
|
|
|
@ -54,22 +54,11 @@ def prompt_user_for_choice(scene_classes):
|
|||
|
||||
|
||||
def get_scene_config(config):
|
||||
return dict([
|
||||
(key, config[key])
|
||||
for key in [
|
||||
"window_config",
|
||||
"camera_config",
|
||||
"file_writer_config",
|
||||
"skip_animations",
|
||||
"start_at_animation_number",
|
||||
"end_at_animation_number",
|
||||
"leave_progress_bars",
|
||||
"show_animation_progress",
|
||||
"preview",
|
||||
"presenter_mode",
|
||||
]
|
||||
])
|
||||
|
||||
scene_parameters = inspect.signature(Scene).parameters.keys()
|
||||
return {
|
||||
key: config[key]
|
||||
for key in set(scene_parameters).intersection(config.keys())
|
||||
}
|
||||
|
||||
def compute_total_frames(scene_class, scene_config):
|
||||
"""
|
||||
|
|
|
@ -657,7 +657,7 @@ class Mobject(object):
|
|||
self.match_updaters(mobject)
|
||||
return self
|
||||
|
||||
def looks_identical(self, mobject: Mobject):
|
||||
def looks_identical(self, mobject: Mobject) -> bool:
|
||||
fam1 = self.family_members_with_points()
|
||||
fam2 = mobject.family_members_with_points()
|
||||
if len(fam1) != len(fam2):
|
||||
|
@ -667,15 +667,20 @@ class Mobject(object):
|
|||
if set(d1).difference(d2):
|
||||
return False
|
||||
for key in d1:
|
||||
eq = (d1[key] == d2[key])
|
||||
if isinstance(eq, bool):
|
||||
if not eq:
|
||||
return False
|
||||
else:
|
||||
if not eq.all():
|
||||
return False
|
||||
if not np.isclose(d1[key], d2[key]).all():
|
||||
return False
|
||||
return True
|
||||
|
||||
def has_same_shape_as(self, mobject: Mobject) -> bool:
|
||||
# Normalize both point sets by centering and making height 1
|
||||
points1, points2 = (
|
||||
(m.get_all_points() - m.get_center()) / m.get_height()
|
||||
for m in (self, mobject)
|
||||
)
|
||||
if len(points1) != len(points2):
|
||||
return False
|
||||
return bool(np.isclose(points1, points2).all())
|
||||
|
||||
# Creating new Mobjects from this one
|
||||
|
||||
def replicate(self, n: int) -> Group:
|
||||
|
@ -1723,7 +1728,7 @@ class Mobject(object):
|
|||
for sm, sm1, sm2 in zip(self.get_family(), mobject1.get_family(), mobject2.get_family()):
|
||||
keys = sm.data.keys() & sm1.data.keys() & sm2.data.keys()
|
||||
sm.lock_data(list(filter(
|
||||
lambda key: np.all(sm1.data[key] == sm2.data[key]),
|
||||
lambda key: (sm1.data[key] == sm2.data[key]).all(),
|
||||
keys,
|
||||
)))
|
||||
return self
|
||||
|
|
|
@ -547,7 +547,7 @@ class StringMobject(SVGMobject, ABC):
|
|||
|
||||
def select_parts(self, selector: Selector) -> VGroup:
|
||||
specified_substrings = self.get_specified_substrings()
|
||||
if isinstance(selector, str) and selector not in specified_substrings:
|
||||
if isinstance(selector, (str, re.Pattern)) and selector not in specified_substrings:
|
||||
return self.select_unisolated_substring(selector)
|
||||
indices_list = self.get_submob_indices_lists_by_selector(selector)
|
||||
return self.build_parts_from_indices_lists(indices_list)
|
||||
|
@ -563,11 +563,14 @@ class StringMobject(SVGMobject, ABC):
|
|||
def substr_to_path_count(self, substr: str) -> int:
|
||||
return len(re.sub(R"\s", "", substr))
|
||||
|
||||
def select_unisolated_substring(self, substr: str) -> VGroup:
|
||||
def select_unisolated_substring(self, pattern: str | re.Pattern) -> VGroup:
|
||||
if isinstance(pattern, str):
|
||||
pattern = re.compile(re.escape(pattern))
|
||||
result = []
|
||||
for match in re.finditer(re.escape(substr), self.string):
|
||||
for match in re.finditer(pattern, self.string):
|
||||
index = match.start()
|
||||
start = self.substr_to_path_count(self.string[:index])
|
||||
substr = match.group()
|
||||
end = start + self.substr_to_path_count(substr)
|
||||
result.append(self[start:end])
|
||||
return VGroup(*result)
|
||||
|
|
|
@ -292,15 +292,13 @@ class VMobjectFromSVGPath(VMobject):
|
|||
def __init__(
|
||||
self,
|
||||
path_obj: se.Path,
|
||||
long_lines: bool = False,
|
||||
should_subdivide_sharp_curves: bool = False,
|
||||
should_remove_null_curves: bool = False,
|
||||
should_remove_null_curves: bool = True,
|
||||
**kwargs
|
||||
):
|
||||
# Get rid of arcs
|
||||
path_obj.approximate_arcs_with_quads()
|
||||
self.path_obj = path_obj
|
||||
self.long_lines = long_lines
|
||||
self.should_subdivide_sharp_curves = should_subdivide_sharp_curves
|
||||
self.should_remove_null_curves = should_remove_null_curves
|
||||
super().__init__(**kwargs)
|
||||
|
|
|
@ -148,11 +148,6 @@ class VMobject(Mobject):
|
|||
raise Exception("All submobjects must be of type VMobject")
|
||||
super().add(*vmobjects)
|
||||
|
||||
def copy(self, deep: bool = False) -> VMobject:
|
||||
result = super().copy(deep)
|
||||
result.shader_wrapper_list = [sw.copy() for sw in self.shader_wrapper_list]
|
||||
return result
|
||||
|
||||
# Colors
|
||||
def init_colors(self):
|
||||
self.set_fill(
|
||||
|
@ -809,6 +804,11 @@ class VMobject(Mobject):
|
|||
# Alignment
|
||||
def align_points(self, vmobject: VMobject):
|
||||
if self.get_num_points() == len(vmobject.get_points()):
|
||||
# If both have fill, and they have the same shape, just
|
||||
# give them the same triangulation so that it's not recalculated
|
||||
# needlessly throughout an animation
|
||||
if self.has_fill() and vmobject.has_fill() and self.has_same_shape_as(vmobject):
|
||||
vmobject.triangulation = self.triangulation
|
||||
return
|
||||
|
||||
for mob in self, vmobject:
|
||||
|
@ -1077,14 +1077,6 @@ class VMobject(Mobject):
|
|||
render_primitive=self.render_primitive,
|
||||
)
|
||||
|
||||
self.shader_wrapper_list = [
|
||||
self.stroke_shader_wrapper.copy(), # Use for back stroke
|
||||
self.fill_shader_wrapper.copy(),
|
||||
self.stroke_shader_wrapper.copy(),
|
||||
]
|
||||
for sw in self.shader_wrapper_list:
|
||||
sw.uniforms = self.uniforms
|
||||
|
||||
def refresh_shader_wrapper_id(self):
|
||||
for wrapper in [self.fill_shader_wrapper, self.stroke_shader_wrapper]:
|
||||
wrapper.refresh_id()
|
||||
|
@ -1107,30 +1099,29 @@ class VMobject(Mobject):
|
|||
# Build up data lists
|
||||
fill_shader_wrappers = []
|
||||
stroke_shader_wrappers = []
|
||||
back_stroke_shader_wrappers = []
|
||||
for submob in self.family_members_with_points():
|
||||
if submob.has_fill():
|
||||
fill_shader_wrappers.append(submob.get_fill_shader_wrapper())
|
||||
if submob.has_stroke():
|
||||
ssw = submob.get_stroke_shader_wrapper()
|
||||
if submob.draw_stroke_behind_fill:
|
||||
back_stroke_shader_wrappers.append(ssw)
|
||||
else:
|
||||
stroke_shader_wrappers.append(ssw)
|
||||
stroke_shader_wrappers.append(submob.get_stroke_shader_wrapper())
|
||||
if submob.draw_stroke_behind_fill:
|
||||
self.draw_stroke_behind_fill = True
|
||||
|
||||
# Combine data lists
|
||||
sw_lists = [
|
||||
back_stroke_shader_wrappers,
|
||||
fill_shader_wrappers,
|
||||
stroke_shader_wrappers,
|
||||
]
|
||||
for sw, sw_list in zip(self.shader_wrapper_list, sw_lists):
|
||||
self_sws = [self.fill_shader_wrapper, self.stroke_shader_wrapper]
|
||||
sw_lists = [fill_shader_wrappers, stroke_shader_wrappers]
|
||||
for sw, sw_list in zip(self_sws, sw_lists):
|
||||
if not sw_list:
|
||||
sw.vert_data = resize_array(sw.vert_data, 0)
|
||||
continue
|
||||
sw.read_in(*sw_list)
|
||||
if sw is sw_list[0]:
|
||||
sw.combine_with(*sw_list[1:])
|
||||
else:
|
||||
sw.read_in(*sw_list)
|
||||
sw.depth_test = any(sw.depth_test for sw in sw_list)
|
||||
sw.uniforms.update(sw_list[0].uniforms)
|
||||
return list(filter(lambda sw: len(sw.vert_data) > 0, self.shader_wrapper_list))
|
||||
if self.draw_stroke_behind_fill:
|
||||
self_sws.reverse()
|
||||
return [sw for sw in self_sws if len(sw.vert_data) > 0]
|
||||
|
||||
def get_stroke_shader_data(self) -> np.ndarray:
|
||||
points = self.get_points()
|
||||
|
|
|
@ -16,15 +16,18 @@ import numpy as np
|
|||
from tqdm import tqdm as ProgressDisplay
|
||||
|
||||
from manimlib.animation.animation import prepare_animation
|
||||
from manimlib.animation.fading import VFadeInThenOut
|
||||
from manimlib.camera.camera import Camera
|
||||
from manimlib.config import get_module
|
||||
from manimlib.constants import ARROW_SYMBOLS
|
||||
from manimlib.constants import DEFAULT_WAIT_TIME
|
||||
from manimlib.constants import COMMAND_MODIFIER
|
||||
from manimlib.constants import SHIFT_MODIFIER
|
||||
from manimlib.constants import RED
|
||||
from manimlib.event_handler import EVENT_DISPATCHER
|
||||
from manimlib.event_handler.event_type import EventType
|
||||
from manimlib.logger import log
|
||||
from manimlib.mobject.frame import FullScreenRectangle
|
||||
from manimlib.mobject.mobject import _AnimationBuilder
|
||||
from manimlib.mobject.mobject import Group
|
||||
from manimlib.mobject.mobject import Mobject
|
||||
|
@ -34,7 +37,6 @@ from manimlib.mobject.types.vectorized_mobject import VMobject
|
|||
from manimlib.scene.scene_file_writer import SceneFileWriter
|
||||
from manimlib.utils.family_ops import extract_mobject_family_members
|
||||
from manimlib.utils.family_ops import recursive_mobject_remove
|
||||
from manimlib.utils.iterables import list_difference_update
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
|
@ -74,6 +76,8 @@ class Scene(object):
|
|||
preview: bool = True,
|
||||
presenter_mode: bool = False,
|
||||
show_animation_progress: bool = False,
|
||||
embed_exception_mode: str = "",
|
||||
embed_error_sound: bool = False,
|
||||
):
|
||||
self.skip_animations = skip_animations
|
||||
self.always_update_mobjects = always_update_mobjects
|
||||
|
@ -83,6 +87,8 @@ class Scene(object):
|
|||
self.preview = preview
|
||||
self.presenter_mode = presenter_mode
|
||||
self.show_animation_progress = show_animation_progress
|
||||
self.embed_exception_mode = embed_exception_mode
|
||||
self.embed_error_sound = embed_error_sound
|
||||
|
||||
self.camera_config = {**self.default_camera_config, **camera_config}
|
||||
self.window_config = {**self.default_window_config, **window_config}
|
||||
|
@ -249,6 +255,22 @@ class Scene(object):
|
|||
|
||||
shell.events.register("post_run_cell", post_cell_func)
|
||||
|
||||
# Flash border, and potentially play sound, on exceptions
|
||||
def custom_exc(shell, etype, evalue, tb, tb_offset=None):
|
||||
# still show the error don't just swallow it
|
||||
shell.showtraceback((etype, evalue, tb), tb_offset=tb_offset)
|
||||
if self.embed_error_sound:
|
||||
os.system("printf '\a'")
|
||||
self.play(VFadeInThenOut(
|
||||
FullScreenRectangle().set_stroke(RED, 30).set_fill(opacity=0),
|
||||
run_time=0.5,
|
||||
))
|
||||
|
||||
shell.set_custom_exc((Exception,), custom_exc)
|
||||
|
||||
# Set desired exception mode
|
||||
shell.magic(f"xmode {self.embed_exception_mode}")
|
||||
|
||||
# Launch shell
|
||||
shell(
|
||||
local_ns=local_ns,
|
||||
|
|
|
@ -131,7 +131,8 @@ class ShaderWrapper(object):
|
|||
self.refresh_id()
|
||||
|
||||
def combine_with(self, *shader_wrappers: ShaderWrapper) -> ShaderWrapper:
|
||||
self.read_in(self.copy(), *shader_wrappers)
|
||||
if len(shader_wrappers) > 0:
|
||||
self.read_in(self.copy(), *shader_wrappers)
|
||||
return self
|
||||
|
||||
def read_in(self, *shader_wrappers: ShaderWrapper) -> ShaderWrapper:
|
||||
|
|
|
@ -1,57 +1,41 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
from functools import lru_cache
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
if TYPE_CHECKING:
|
||||
from typing import List, Tuple
|
||||
|
||||
|
||||
@lru_cache(maxsize=1)
|
||||
def get_pattern_symbol_count_pairs() -> List[Tuple[str, int]]:
|
||||
from manimlib.utils.tex_to_symbol_count import TEX_TO_SYMBOL_COUNT
|
||||
|
||||
# Gather all keys of previous map, grouped by common value
|
||||
count_to_tex_list = dict()
|
||||
for command, num in TEX_TO_SYMBOL_COUNT.items():
|
||||
if num not in count_to_tex_list:
|
||||
count_to_tex_list[num] = []
|
||||
count_to_tex_list[num].append(command)
|
||||
|
||||
# Create a list associating each count with a regular expression
|
||||
# that will find any tex commands matching that list
|
||||
pattern_symbol_count_pairs = list()
|
||||
|
||||
# Account for patterns like \begin{align} and \phantom{thing}
|
||||
# which, together with the bracketed content account for zero paths.
|
||||
# Deliberately put this first in the list
|
||||
tex_list = ["begin", "end", "phantom"]
|
||||
pattern_symbol_count_pairs.append(
|
||||
("|".join(r"\\" + s + r"\{[^\\}]+\}" for s in tex_list), 0)
|
||||
)
|
||||
|
||||
for count, tex_list in count_to_tex_list.items():
|
||||
pattern = "|".join(r"\\" + s for s in tex_list)
|
||||
pattern_symbol_count_pairs.append((pattern, count))
|
||||
|
||||
# Assume all other expressions of the form \thing are drawn with one path
|
||||
# Deliberately put this last in the list
|
||||
pattern_symbol_count_pairs.append((r"\\[a-zA-Z]+", 1))
|
||||
|
||||
return pattern_symbol_count_pairs
|
||||
from manimlib.utils.tex_to_symbol_count import TEX_TO_SYMBOL_COUNT
|
||||
|
||||
|
||||
def num_tex_symbols(tex: str) -> int:
|
||||
"""
|
||||
This function attempts to estimate the number of symbols that
|
||||
a given string of tex would produce.
|
||||
|
||||
Warning, it may not behave perfectly
|
||||
"""
|
||||
# First, remove patterns like \begin{align}, \phantom{thing},
|
||||
# \begin{array}{cc}, etc.
|
||||
pattern = "|".join(
|
||||
r"(\\" + s + ")" + r"(\{\w+\})?(\{\w+\})?(\[\w+\])?"
|
||||
for s in ["begin", "end", "phantom"]
|
||||
)
|
||||
for tup in re.findall(pattern, tex):
|
||||
tex = tex.replace("".join(tup), " ")
|
||||
|
||||
# Progressively count the symbols associated with certain tex commands,
|
||||
# and remove those commands from the string, adding the number of symbols
|
||||
# that command creates
|
||||
total = 0
|
||||
for pattern, count in get_pattern_symbol_count_pairs():
|
||||
total += count * len(re.findall(pattern, tex))
|
||||
tex = re.sub(pattern, " ", tex) # Remove that pattern
|
||||
|
||||
# Start with the special case \sqrt[number]
|
||||
for substr in re.findall(r"\\sqrt\[[0-9]+\]", tex):
|
||||
total += len(substr) - 5 # e.g. \sqrt[3] is 3 symbols
|
||||
tex = tex.replace(substr, " ")
|
||||
|
||||
general_command = r"\\[a-zA-Z!,-/:;<>]+"
|
||||
for substr in re.findall(general_command, tex):
|
||||
total += TEX_TO_SYMBOL_COUNT.get(substr, 1)
|
||||
tex = tex.replace(substr, " ")
|
||||
|
||||
# Count remaining characters
|
||||
total += sum(map(lambda c: c not in "^{} \n\t_$", tex))
|
||||
total += sum(map(lambda c: c not in "^{} \n\t_$\\&", tex))
|
||||
return total
|
||||
|
|
|
@ -1,182 +1,181 @@
|
|||
TEX_TO_SYMBOL_COUNT = {
|
||||
"!": 0,
|
||||
",": 0,
|
||||
",": 0,
|
||||
"-": 0,
|
||||
"-": 0,
|
||||
"/": 0,
|
||||
":": 0,
|
||||
";": 0,
|
||||
";": 0,
|
||||
">": 0,
|
||||
"aa": 0,
|
||||
"AA": 0,
|
||||
"ae": 0,
|
||||
"AE": 0,
|
||||
"arccos": 6,
|
||||
"arcsin": 6,
|
||||
"arctan": 6,
|
||||
"arg": 3,
|
||||
"author": 0,
|
||||
"bf": 0,
|
||||
"bibliography": 0,
|
||||
"bibliographystyle": 0,
|
||||
"big": 0,
|
||||
"Big": 0,
|
||||
"bigodot": 4,
|
||||
"bigoplus": 5,
|
||||
"bigskip": 0,
|
||||
"bmod": 3,
|
||||
"boldmath": 0,
|
||||
"bottomfraction": 2,
|
||||
"bowtie": 2,
|
||||
"cal": 0,
|
||||
"cdots": 3,
|
||||
"centering": 0,
|
||||
"cite": 2,
|
||||
"cong": 2,
|
||||
"contentsline": 0,
|
||||
"cos": 3,
|
||||
"cosh": 4,
|
||||
"cot": 3,
|
||||
"coth": 4,
|
||||
"csc": 3,
|
||||
"date": 0,
|
||||
"dblfloatpagefraction": 2,
|
||||
"dbltopfraction": 2,
|
||||
"ddots": 3,
|
||||
"deg": 3,
|
||||
"det": 3,
|
||||
"dim": 3,
|
||||
"displaystyle": 0,
|
||||
"div": 2,
|
||||
"doteq": 2,
|
||||
"dotfill": 0,
|
||||
"emph": 0,
|
||||
"exp": 3,
|
||||
"fbox": 4,
|
||||
"floatpagefraction": 2,
|
||||
"flushbottom": 0,
|
||||
"footnotesize": 0,
|
||||
"footnotetext": 0,
|
||||
"frame": 2,
|
||||
"framebox": 4,
|
||||
"fussy": 0,
|
||||
"gcd": 3,
|
||||
"ghost": 0,
|
||||
"glossary": 0,
|
||||
"hfill": 0,
|
||||
"hom": 3,
|
||||
"hookleftarrow": 2,
|
||||
"hookrightarrow": 2,
|
||||
"hrulefill": 0,
|
||||
"huge": 0,
|
||||
"Huge": 0,
|
||||
"hyphenation": 0,
|
||||
"iff": 2,
|
||||
"Im": 2,
|
||||
"index": 0,
|
||||
"inf": 3,
|
||||
"it": 0,
|
||||
"ker": 3,
|
||||
"l": 0,
|
||||
"L": 0,
|
||||
"label": 0,
|
||||
"large": 0,
|
||||
"Large": 0,
|
||||
"LARGE": 0,
|
||||
"ldots": 3,
|
||||
"lefteqn": 0,
|
||||
"lg": 2,
|
||||
"lim": 3,
|
||||
"liminf": 6,
|
||||
"limsup": 6,
|
||||
"linebreak": 0,
|
||||
"ln": 2,
|
||||
"log": 3,
|
||||
"longleftarrow": 2,
|
||||
"Longleftarrow": 2,
|
||||
"longleftrightarrow": 2,
|
||||
"Longleftrightarrow": 2,
|
||||
"longmapsto": 3,
|
||||
"longrightarrow": 2,
|
||||
"Longrightarrow": 2,
|
||||
"makebox": 0,
|
||||
"mapsto": 2,
|
||||
"markright": 0,
|
||||
"max": 3,
|
||||
"mbox": 0,
|
||||
"medskip": 0,
|
||||
"min": 3,
|
||||
"mit": 0,
|
||||
"models": 2,
|
||||
"ne": 2,
|
||||
"neq": 2,
|
||||
"newline": 0,
|
||||
"noindent": 0,
|
||||
"nolinebreak": 0,
|
||||
"nonumber": 0,
|
||||
"nopagebreak": 0,
|
||||
"normalmarginpar": 0,
|
||||
"normalsize": 0,
|
||||
"notin": 2,
|
||||
"o": 0,
|
||||
"O": 0,
|
||||
"obeycr": 0,
|
||||
"oe": 0,
|
||||
"OE": 0,
|
||||
"overbrace": 4,
|
||||
"pagebreak": 0,
|
||||
"pagenumbering": 0,
|
||||
"pageref": 2,
|
||||
"pmod": 5,
|
||||
"Pr": 2,
|
||||
"protect": 0,
|
||||
"qquad": 0,
|
||||
"quad": 0,
|
||||
"raggedbottom": 0,
|
||||
"raggedleft": 0,
|
||||
"raggedright": 0,
|
||||
"Re": 2,
|
||||
"ref": 2,
|
||||
"restorecr": 0,
|
||||
"reversemarginpar": 0,
|
||||
"rm": 0,
|
||||
"sc": 0,
|
||||
"scriptscriptstyle": 0,
|
||||
"scriptsize": 0,
|
||||
"scriptstyle": 0,
|
||||
"sec": 3,
|
||||
"sf": 0,
|
||||
"shortstack": 0,
|
||||
"sin": 3,
|
||||
"sinh": 4,
|
||||
"sl": 0,
|
||||
"sloppy": 0,
|
||||
"small": 0,
|
||||
"Small": 0,
|
||||
"smallskip": 0,
|
||||
"sqrt": 2,
|
||||
"ss": 0,
|
||||
"sup": 3,
|
||||
"tan": 3,
|
||||
"tanh": 4,
|
||||
"textbf": 0,
|
||||
"textfraction": 2,
|
||||
"textstyle": 0,
|
||||
"thicklines": 0,
|
||||
"thinlines": 0,
|
||||
"thinspace": 0,
|
||||
"tiny": 0,
|
||||
"title": 0,
|
||||
"today": 15,
|
||||
"topfraction": 2,
|
||||
"tt": 0,
|
||||
"typeout": 0,
|
||||
"unboldmath": 0,
|
||||
"underbrace": 6,
|
||||
"underline": 0,
|
||||
"value": 0,
|
||||
"vdots": 3,
|
||||
"vline": 0
|
||||
R"\!": 0,
|
||||
R"\,": 0,
|
||||
R"\-": 0,
|
||||
R"\/": 0,
|
||||
R"\:": 0,
|
||||
R"\;": 0,
|
||||
R"\>": 0,
|
||||
R"\aa": 0,
|
||||
R"\AA": 0,
|
||||
R"\ae": 0,
|
||||
R"\AE": 0,
|
||||
R"\arccos": 6,
|
||||
R"\arcsin": 6,
|
||||
R"\arctan": 6,
|
||||
R"\arg": 3,
|
||||
R"\author": 0,
|
||||
R"\bf": 0,
|
||||
R"\bibliography": 0,
|
||||
R"\bibliographystyle": 0,
|
||||
R"\big": 0,
|
||||
R"\Big": 0,
|
||||
R"\bigodot": 4,
|
||||
R"\bigoplus": 5,
|
||||
R"\bigskip": 0,
|
||||
R"\bmod": 3,
|
||||
R"\boldmath": 0,
|
||||
R"\bottomfraction": 2,
|
||||
R"\bowtie": 2,
|
||||
R"\cal": 0,
|
||||
R"\cdots": 3,
|
||||
R"\centering": 0,
|
||||
R"\cite": 2,
|
||||
R"\cong": 2,
|
||||
R"\contentsline": 0,
|
||||
R"\cos": 3,
|
||||
R"\cosh": 4,
|
||||
R"\cot": 3,
|
||||
R"\coth": 4,
|
||||
R"\csc": 3,
|
||||
R"\date": 0,
|
||||
R"\dblfloatpagefraction": 2,
|
||||
R"\dbltopfraction": 2,
|
||||
R"\ddots": 3,
|
||||
R"\deg": 3,
|
||||
R"\det": 3,
|
||||
R"\dim": 3,
|
||||
R"\displaystyle": 0,
|
||||
R"\div": 2,
|
||||
R"\doteq": 2,
|
||||
R"\dotfill": 0,
|
||||
R"\emph": 0,
|
||||
R"\exp": 3,
|
||||
R"\fbox": 4,
|
||||
R"\floatpagefraction": 2,
|
||||
R"\flushbottom": 0,
|
||||
R"\footnotesize": 0,
|
||||
R"\footnotetext": 0,
|
||||
R"\frame": 2,
|
||||
R"\framebox": 4,
|
||||
R"\fussy": 0,
|
||||
R"\gcd": 3,
|
||||
R"\ghost": 0,
|
||||
R"\glossary": 0,
|
||||
R"\hfill": 0,
|
||||
R"\hom": 3,
|
||||
R"\hookleftarrow": 2,
|
||||
R"\hookrightarrow": 2,
|
||||
R"\hrulefill": 0,
|
||||
R"\huge": 0,
|
||||
R"\Huge": 0,
|
||||
R"\hyphenation": 0,
|
||||
R"\iff": 2,
|
||||
R"\Im": 2,
|
||||
R"\index": 0,
|
||||
R"\inf": 3,
|
||||
R"\it": 0,
|
||||
R"\ker": 3,
|
||||
R"\l": 0,
|
||||
R"\L": 0,
|
||||
R"\label": 0,
|
||||
R"\large": 0,
|
||||
R"\Large": 0,
|
||||
R"\LARGE": 0,
|
||||
R"\ldots": 3,
|
||||
R"\lefteqn": 0,
|
||||
R"\left": 0,
|
||||
R"\lg": 2,
|
||||
R"\lim": 3,
|
||||
R"\liminf": 6,
|
||||
R"\limsup": 6,
|
||||
R"\linebreak": 0,
|
||||
R"\ln": 2,
|
||||
R"\log": 3,
|
||||
R"\longleftarrow": 2,
|
||||
R"\Longleftarrow": 2,
|
||||
R"\longleftrightarrow": 2,
|
||||
R"\Longleftrightarrow": 2,
|
||||
R"\longmapsto": 3,
|
||||
R"\longrightarrow": 2,
|
||||
R"\Longrightarrow": 2,
|
||||
R"\makebox": 0,
|
||||
R"\mapsto": 2,
|
||||
R"\markright": 0,
|
||||
R"\max": 3,
|
||||
R"\mbox": 0,
|
||||
R"\medskip": 0,
|
||||
R"\min": 3,
|
||||
R"\mit": 0,
|
||||
R"\models": 2,
|
||||
R"\ne": 2,
|
||||
R"\neq": 2,
|
||||
R"\newline": 0,
|
||||
R"\noindent": 0,
|
||||
R"\nolinebreak": 0,
|
||||
R"\nonumber": 0,
|
||||
R"\nopagebreak": 0,
|
||||
R"\normalmarginpar": 0,
|
||||
R"\normalsize": 0,
|
||||
R"\notin": 2,
|
||||
R"\o": 0,
|
||||
R"\O": 0,
|
||||
R"\obeycr": 0,
|
||||
R"\oe": 0,
|
||||
R"\OE": 0,
|
||||
R"\overbrace": 4,
|
||||
R"\pagebreak": 0,
|
||||
R"\pagenumbering": 0,
|
||||
R"\pageref": 2,
|
||||
R"\pmod": 5,
|
||||
R"\Pr": 2,
|
||||
R"\protect": 0,
|
||||
R"\qquad": 0,
|
||||
R"\quad": 0,
|
||||
R"\raggedbottom": 0,
|
||||
R"\raggedleft": 0,
|
||||
R"\raggedright": 0,
|
||||
R"\Re": 2,
|
||||
R"\ref": 2,
|
||||
R"\restorecr": 0,
|
||||
R"\reversemarginpar": 0,
|
||||
R"\right": 0,
|
||||
R"\rm": 0,
|
||||
R"\sc": 0,
|
||||
R"\scriptscriptstyle": 0,
|
||||
R"\scriptsize": 0,
|
||||
R"\scriptstyle": 0,
|
||||
R"\sec": 3,
|
||||
R"\sf": 0,
|
||||
R"\shortstack": 0,
|
||||
R"\sin": 3,
|
||||
R"\sinh": 4,
|
||||
R"\sl": 0,
|
||||
R"\sloppy": 0,
|
||||
R"\small": 0,
|
||||
R"\Small": 0,
|
||||
R"\smallskip": 0,
|
||||
R"\sqrt": 2,
|
||||
R"\ss": 0,
|
||||
R"\sup": 3,
|
||||
R"\tan": 3,
|
||||
R"\tanh": 4,
|
||||
R"\textbf": 0,
|
||||
R"\textfraction": 2,
|
||||
R"\textstyle": 0,
|
||||
R"\thicklines": 0,
|
||||
R"\thinlines": 0,
|
||||
R"\thinspace": 0,
|
||||
R"\tiny": 0,
|
||||
R"\title": 0,
|
||||
R"\today": 15,
|
||||
R"\topfraction": 2,
|
||||
R"\tt": 0,
|
||||
R"\typeout": 0,
|
||||
R"\unboldmath": 0,
|
||||
R"\underbrace": 6,
|
||||
R"\underline": 0,
|
||||
R"\value": 0,
|
||||
R"\vdots": 3,
|
||||
R"\vline": 0
|
||||
}
|
Loading…
Add table
Reference in a new issue