mirror of
https://github.com/3b1b/manim.git
synced 2025-08-02 19:46:21 +08:00
Refactor topics/numerals into various numbers.py files in mobject/, animation/, and continual_animation/
This commit is contained in:
61
animation/numbers.py
Normal file
61
animation/numbers.py
Normal file
@ -0,0 +1,61 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
from constants import *
|
||||
|
||||
from animation.animation import Animation
|
||||
from mobject.numbers import DecimalNumber
|
||||
from utils.bezier import interpolate
|
||||
from utils.config_ops import digest_config
|
||||
|
||||
class ChangingDecimal(Animation):
|
||||
CONFIG = {
|
||||
"num_decimal_points" : None,
|
||||
"show_ellipsis" : None,
|
||||
"position_update_func" : None,
|
||||
"tracked_mobject" : None,
|
||||
}
|
||||
def __init__(self, decimal_number_mobject, number_update_func, **kwargs):
|
||||
digest_config(self, kwargs, locals())
|
||||
self.decimal_number_config = dict(
|
||||
decimal_number_mobject.initial_config
|
||||
)
|
||||
for attr in "num_decimal_points", "show_ellipsis":
|
||||
value = getattr(self, attr)
|
||||
if value is not None:
|
||||
self.decimal_number_config[attr] = value
|
||||
if hasattr(self.decimal_number_mobject, "background_rectangle"):
|
||||
self.decimal_number_config["include_background_rectangle"] = True
|
||||
if self.tracked_mobject:
|
||||
dmc = decimal_number_mobject.get_center()
|
||||
tmc = self.tracked_mobject.get_center()
|
||||
self.diff_from_tracked_mobject = dmc - tmc
|
||||
Animation.__init__(self, decimal_number_mobject, **kwargs)
|
||||
|
||||
def update_mobject(self, alpha):
|
||||
self.update_number(alpha)
|
||||
self.update_position()
|
||||
|
||||
def update_number(self, alpha):
|
||||
decimal = self.decimal_number_mobject
|
||||
new_number = self.number_update_func(alpha)
|
||||
new_decimal = DecimalNumber(
|
||||
new_number, **self.decimal_number_config
|
||||
)
|
||||
new_decimal.match_height(decimal)
|
||||
new_decimal.move_to(decimal)
|
||||
new_decimal.match_style(decimal)
|
||||
|
||||
decimal.submobjects = new_decimal.submobjects
|
||||
decimal.number = new_number
|
||||
|
||||
def update_position(self):
|
||||
if self.position_update_func is not None:
|
||||
self.position_update_func(self.decimal_number_mobject)
|
||||
elif self.tracked_mobject is not None:
|
||||
self.decimal_number_mobject.move_to(self.tracked_mobject.get_center() + self.diff_from_tracked_mobject)
|
||||
|
||||
class ChangeDecimalToValue(ChangingDecimal):
|
||||
def __init__(self, decimal_number_mobject, target_number, **kwargs):
|
||||
start_number = decimal_number_mobject.number
|
||||
func = lambda alpha : interpolate(start_number, target_number, alpha)
|
||||
ChangingDecimal.__init__(self, decimal_number_mobject, func, **kwargs)
|
@ -20,6 +20,7 @@ from animation.composition import *
|
||||
from animation.creation import *
|
||||
from animation.indication import *
|
||||
from animation.movement import *
|
||||
from animation.numbers import *
|
||||
from animation.rotation import *
|
||||
from animation.specialized import *
|
||||
from animation.transform import *
|
||||
@ -31,11 +32,13 @@ from camera.moving_camera import *
|
||||
|
||||
from continual_animation.continual_animation import *
|
||||
from continual_animation.from_animation import *
|
||||
from continual_animation.numbers import *
|
||||
from continual_animation.update import *
|
||||
|
||||
from mobject.mobject import *
|
||||
from mobject.frame import *
|
||||
from mobject.geometry import *
|
||||
from mobject.numbers import *
|
||||
from mobject.shape_matchers import *
|
||||
from mobject.value_tracker import *
|
||||
from mobject.svg.brace import *
|
||||
@ -68,7 +71,6 @@ from topics.functions import *
|
||||
from topics.graph_scene import *
|
||||
from topics.matrix import *
|
||||
from topics.number_line import *
|
||||
from topics.numerals import *
|
||||
from topics.probability import *
|
||||
from topics.three_dimensions import *
|
||||
from topics.vector_space_scene import *
|
||||
|
10
continual_animation/numbers.py
Normal file
10
continual_animation/numbers.py
Normal file
@ -0,0 +1,10 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
from continual_animation.from_animation import NormalAnimationAsContinualAnimation
|
||||
from animation.numbers import ChangingDecimal
|
||||
|
||||
class ContinualChangingDecimal(NormalAnimationAsContinualAnimation):
|
||||
def __init__(self, *args, **kwargs):
|
||||
NormalAnimationAsContinualAnimation.__init__(
|
||||
self, ChangingDecimal(*args, **kwargs)
|
||||
)
|
85
mobject/numbers.py
Normal file
85
mobject/numbers.py
Normal file
@ -0,0 +1,85 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
from constants import *
|
||||
|
||||
from mobject.svg.tex_mobject import TexMobject
|
||||
from mobject.types.vectorized_mobject import VGroup
|
||||
from mobject.types.vectorized_mobject import VMobject
|
||||
from mobject.shape_matchers import BackgroundRectangle
|
||||
|
||||
class DecimalNumber(VMobject):
|
||||
CONFIG = {
|
||||
"num_decimal_points" : 2,
|
||||
"digit_to_digit_buff" : 0.05,
|
||||
"show_ellipsis" : False,
|
||||
"unit" : None, #Aligned to bottom unless it starts with "^"
|
||||
"include_background_rectangle" : False,
|
||||
}
|
||||
def __init__(self, number, **kwargs):
|
||||
VMobject.__init__(self, **kwargs)
|
||||
self.number = number
|
||||
ndp = self.num_decimal_points
|
||||
|
||||
#Build number string
|
||||
if isinstance(number, complex):
|
||||
num_string = '%.*f%s%.*fi'%(
|
||||
ndp, number.real,
|
||||
"-" if number.imag < 0 else "+",
|
||||
ndp, abs(number.imag)
|
||||
)
|
||||
else:
|
||||
num_string = '%.*f'%(ndp, number)
|
||||
negative_zero_string = "-%.*f"%(ndp, 0.)
|
||||
if num_string == negative_zero_string:
|
||||
num_string = num_string[1:]
|
||||
self.add(*[
|
||||
TexMobject(char, **kwargs)
|
||||
for char in num_string
|
||||
])
|
||||
|
||||
#Add non-numerical bits
|
||||
if self.show_ellipsis:
|
||||
self.add(TexMobject("\\dots"))
|
||||
|
||||
|
||||
if num_string.startswith("-"):
|
||||
minus = self.submobjects[0]
|
||||
minus.next_to(
|
||||
self.submobjects[1], LEFT,
|
||||
buff = self.digit_to_digit_buff
|
||||
)
|
||||
|
||||
if self.unit != None:
|
||||
self.unit_sign = TexMobject(self.unit)
|
||||
self.add(self.unit_sign)
|
||||
|
||||
self.arrange_submobjects(
|
||||
buff = self.digit_to_digit_buff,
|
||||
aligned_edge = DOWN
|
||||
)
|
||||
|
||||
#Handle alignment of parts that should be aligned
|
||||
#to the bottom
|
||||
for i, c in enumerate(num_string):
|
||||
if c == "-" and len(num_string) > i+1:
|
||||
self[i].align_to(self[i+1], alignment_vect = UP)
|
||||
if self.unit and self.unit.startswith("^"):
|
||||
self.unit_sign.align_to(self, UP)
|
||||
#
|
||||
if self.include_background_rectangle:
|
||||
self.add_background_rectangle()
|
||||
|
||||
def add_background_rectangle(self):
|
||||
#TODO, is this the best way to handle
|
||||
#background rectangles?
|
||||
self.background_rectangle = BackgroundRectangle(self)
|
||||
self.submobjects = [
|
||||
self.background_rectangle,
|
||||
VGroup(*self.submobjects)
|
||||
]
|
||||
return self
|
||||
|
||||
class Integer(DecimalNumber):
|
||||
CONFIG = {
|
||||
"num_decimal_points" : 0,
|
||||
}
|
@ -1,169 +0,0 @@
|
||||
|
||||
from animation.animation import Animation
|
||||
from constants import *
|
||||
from continual_animation.continual_animation import ContinualAnimation
|
||||
from mobject.svg.tex_mobject import TexMobject
|
||||
from mobject.types.vectorized_mobject import VGroup
|
||||
from mobject.types.vectorized_mobject import VMobject
|
||||
from mobject.types.vectorized_mobject import VectorizedPoint
|
||||
from scene.scene import Scene
|
||||
from mobject.shape_matchers import BackgroundRectangle
|
||||
from utils.bezier import interpolate
|
||||
from utils.config_ops import digest_config
|
||||
|
||||
class DecimalNumber(VMobject):
|
||||
CONFIG = {
|
||||
"num_decimal_points" : 2,
|
||||
"digit_to_digit_buff" : 0.05,
|
||||
"show_ellipsis" : False,
|
||||
"unit" : None, #Aligned to bottom unless it starts with "^"
|
||||
"include_background_rectangle" : False,
|
||||
}
|
||||
def __init__(self, number, **kwargs):
|
||||
VMobject.__init__(self, **kwargs)
|
||||
self.number = number
|
||||
ndp = self.num_decimal_points
|
||||
|
||||
#Build number string
|
||||
if isinstance(number, complex):
|
||||
num_string = '%.*f%s%.*fi'%(
|
||||
ndp, number.real,
|
||||
"-" if number.imag < 0 else "+",
|
||||
ndp, abs(number.imag)
|
||||
)
|
||||
else:
|
||||
num_string = '%.*f'%(ndp, number)
|
||||
negative_zero_string = "-%.*f"%(ndp, 0.)
|
||||
if num_string == negative_zero_string:
|
||||
num_string = num_string[1:]
|
||||
self.add(*[
|
||||
TexMobject(char, **kwargs)
|
||||
for char in num_string
|
||||
])
|
||||
|
||||
#Add non-numerical bits
|
||||
if self.show_ellipsis:
|
||||
self.add(TexMobject("\\dots"))
|
||||
|
||||
|
||||
if num_string.startswith("-"):
|
||||
minus = self.submobjects[0]
|
||||
minus.next_to(
|
||||
self.submobjects[1], LEFT,
|
||||
buff = self.digit_to_digit_buff
|
||||
)
|
||||
|
||||
if self.unit != None:
|
||||
self.unit_sign = TexMobject(self.unit)
|
||||
self.add(self.unit_sign)
|
||||
|
||||
self.arrange_submobjects(
|
||||
buff = self.digit_to_digit_buff,
|
||||
aligned_edge = DOWN
|
||||
)
|
||||
|
||||
#Handle alignment of parts that should be aligned
|
||||
#to the bottom
|
||||
for i, c in enumerate(num_string):
|
||||
if c == "-" and len(num_string) > i+1:
|
||||
self[i].align_to(self[i+1], alignment_vect = UP)
|
||||
if self.unit and self.unit.startswith("^"):
|
||||
self.unit_sign.align_to(self, UP)
|
||||
#
|
||||
if self.include_background_rectangle:
|
||||
self.add_background_rectangle()
|
||||
|
||||
def add_background_rectangle(self):
|
||||
#TODO, is this the best way to handle
|
||||
#background rectangles?
|
||||
self.background_rectangle = BackgroundRectangle(self)
|
||||
self.submobjects = [
|
||||
self.background_rectangle,
|
||||
VGroup(*self.submobjects)
|
||||
]
|
||||
return self
|
||||
|
||||
class Integer(DecimalNumber):
|
||||
CONFIG = {
|
||||
"num_decimal_points" : 0,
|
||||
}
|
||||
|
||||
class ChangingDecimal(Animation):
|
||||
CONFIG = {
|
||||
"num_decimal_points" : None,
|
||||
"show_ellipsis" : None,
|
||||
"position_update_func" : None,
|
||||
"tracked_mobject" : None,
|
||||
}
|
||||
def __init__(self, decimal_number_mobject, number_update_func, **kwargs):
|
||||
digest_config(self, kwargs, locals())
|
||||
self.decimal_number_config = dict(
|
||||
decimal_number_mobject.initial_config
|
||||
)
|
||||
for attr in "num_decimal_points", "show_ellipsis":
|
||||
value = getattr(self, attr)
|
||||
if value is not None:
|
||||
self.decimal_number_config[attr] = value
|
||||
if hasattr(self.decimal_number_mobject, "background_rectangle"):
|
||||
self.decimal_number_config["include_background_rectangle"] = True
|
||||
if self.tracked_mobject:
|
||||
dmc = decimal_number_mobject.get_center()
|
||||
tmc = self.tracked_mobject.get_center()
|
||||
self.diff_from_tracked_mobject = dmc - tmc
|
||||
Animation.__init__(self, decimal_number_mobject, **kwargs)
|
||||
|
||||
def update_mobject(self, alpha):
|
||||
self.update_number(alpha)
|
||||
self.update_position()
|
||||
|
||||
def update_number(self, alpha):
|
||||
decimal = self.decimal_number_mobject
|
||||
new_number = self.number_update_func(alpha)
|
||||
new_decimal = DecimalNumber(
|
||||
new_number, **self.decimal_number_config
|
||||
)
|
||||
new_decimal.match_height(decimal)
|
||||
new_decimal.move_to(decimal)
|
||||
new_decimal.match_style(decimal)
|
||||
|
||||
decimal.submobjects = new_decimal.submobjects
|
||||
decimal.number = new_number
|
||||
|
||||
def update_position(self):
|
||||
if self.position_update_func is not None:
|
||||
self.position_update_func(self.decimal_number_mobject)
|
||||
elif self.tracked_mobject is not None:
|
||||
self.decimal_number_mobject.move_to(self.tracked_mobject.get_center() + self.diff_from_tracked_mobject)
|
||||
|
||||
class ChangeDecimalToValue(ChangingDecimal):
|
||||
def __init__(self, decimal_number_mobject, target_number, **kwargs):
|
||||
start_number = decimal_number_mobject.number
|
||||
func = lambda alpha : interpolate(start_number, target_number, alpha)
|
||||
ChangingDecimal.__init__(self, decimal_number_mobject, func, **kwargs)
|
||||
|
||||
class ContinualChangingDecimal(ContinualAnimation):
|
||||
def __init__(self, decimal_number_mobject, number_update_func, **kwargs):
|
||||
self.anim = ChangingDecimal(decimal_number_mobject, number_update_func, **kwargs)
|
||||
ContinualAnimation.__init__(self, decimal_number_mobject, **kwargs)
|
||||
|
||||
def update_mobject(self, dt):
|
||||
self.anim.update(self.internal_time)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user