Animation engine for explanatory math videos with programmatic mathematical visualization capabilities
—
ManimGL provides extensive utilities and constants that support animation development, mathematical operations, and visual styling. These include mathematical constants, color definitions, rate functions, vector operations, and development tools.
Fundamental mathematical constants for calculations and positioning.
# Mathematical constants
PI = 3.141592653589793
TAU = 6.283185307179586 # 2 * PI
E = 2.718281828459045
# Angle conversion
DEGREES = PI / 180
RADIANS = 1
DEG = DEGREES
# Common angles
RIGHT_ANGLE = PI / 2
STRAIGHT_ANGLE = PI
FULL_ROTATION = TAUStandard directional vectors for positioning and movement.
# Cardinal directions (3D vectors)
ORIGIN = np.array([0.0, 0.0, 0.0])
UP = np.array([0.0, 1.0, 0.0])
DOWN = np.array([0.0, -1.0, 0.0])
LEFT = np.array([-1.0, 0.0, 0.0])
RIGHT = np.array([1.0, 0.0, 0.0])
IN = np.array([0.0, 0.0, -1.0])
OUT = np.array([0.0, 0.0, 1.0])
# Axis vectors
X_AXIS = np.array([1.0, 0.0, 0.0])
Y_AXIS = np.array([0.0, 1.0, 0.0])
Z_AXIS = np.array([0.0, 0.0, 1.0])
# Diagonal directions
UL = UP + LEFT # Up-Left
UR = UP + RIGHT # Up-Right
DL = DOWN + LEFT # Down-Left
DR = DOWN + RIGHT # Down-Right
# Normalized diagonal directions
normalize = lambda v: v / np.linalg.norm(v)
UL = normalize(UL)
UR = normalize(UR)
DL = normalize(DL)
DR = normalize(DR)Constants for scene dimensions and spacing.
# Frame dimensions
FRAME_HEIGHT = 8.0
FRAME_WIDTH = 14.222222222222221 # 16:9 aspect ratio
FRAME_SHAPE = (FRAME_HEIGHT, FRAME_WIDTH)
FRAME_X_RADIUS = FRAME_WIDTH / 2
FRAME_Y_RADIUS = FRAME_HEIGHT / 2
# Frame edges
TOP = FRAME_Y_RADIUS * UP
BOTTOM = FRAME_Y_RADIUS * DOWN
LEFT_SIDE = FRAME_X_RADIUS * LEFT
RIGHT_SIDE = FRAME_X_RADIUS * RIGHT
# Standard spacing
SMALL_BUFF = 0.1
MED_SMALL_BUFF = 0.25
MED_LARGE_BUFF = 0.5
LARGE_BUFF = 1.0
DEFAULT_MOBJECT_TO_EDGE_BUFFER = MED_LARGE_BUFF
DEFAULT_MOBJECT_TO_MOBJECT_BUFFER = MED_SMALL_BUFFComprehensive color palette for styling objects and animations.
# Primary colors
BLACK = "#000000"
WHITE = "#FFFFFF"
GREY = GRAY = "#888888"
RED = "#FC6255"
GREEN = "#58C4DD"
BLUE = "#5DEDE8"
YELLOW = "#F0F91A"
PURPLE = "#BC85FF"
ORANGE = "#FFAB00"
PINK = "#FF006E"
# Color intensity variants (A=darkest, E=lightest)
BLUE_A = "#0E4B99"
BLUE_B = "#2E74B5"
BLUE_C = "#5DEDE8" # Standard BLUE
BLUE_D = "#83C9E2"
BLUE_E = "#A8D8EA"
GREEN_A = "#2FA933"
GREEN_B = "#4CBB17"
GREEN_C = "#58C4DD" # Standard GREEN
GREEN_D = "#83DDDD"
GREEN_E = "#A8E6CF"
RED_A = "#8B0000"
RED_B = "#CD212A"
RED_C = "#FC6255" # Standard RED
RED_D = "#FF8080"
RED_E = "#FFA8A8"
YELLOW_A = "#E1A95F"
YELLOW_B = "#F4D03F"
YELLOW_C = "#F0F91A" # Standard YELLOW
YELLOW_D = "#FFFF7F"
YELLOW_E = "#FFFFCC"
PURPLE_A = "#644172"
PURPLE_B = "#7759A9"
PURPLE_C = "#BC85FF" # Standard PURPLE
PURPLE_D = "#D2A9F0"
PURPLE_E = "#E8D5FF"
# Special colors
MAROON = "#C32148"
TEAL = "#49A88F"
GOLD = "#C78D46"
GREY_BROWN = "#736357"
DARK_BROWN = "#8B4513"
LIGHT_BROWN = "#CD853F"
GREEN_SCREEN = "#00FF00"
# Color collections
MANIM_COLORS = [
BLUE_C, GREEN_C, RED_C, YELLOW_C, PURPLE_C,
ORANGE, PINK, TEAL, GOLD, MAROON
]
COLORMAP_3B1B = {
"BLUE": BLUE,
"GREEN": GREEN,
"RED": RED,
"YELLOW": YELLOW,
"PURPLE": PURPLE
}Animation timing functions that control the pacing and easing of animations.
def linear(t):
"""
Linear interpolation (constant speed).
Parameters:
- t: float, time parameter (0-1)
Returns:
float, interpolated value (0-1)
"""
return t
def smooth(t):
"""
Smooth ease in/out using cubic interpolation.
Parameters:
- t: float, time parameter (0-1)
Returns:
float, smoothed value (0-1)
"""
return 3*t**2 - 2*t**3
def rush_into(t):
"""
Slow start, accelerating finish.
Parameters:
- t: float, time parameter (0-1)
Returns:
float, eased value (0-1)
"""
return 2 * smooth(t / 2.0)
def rush_from(t):
"""
Fast start, decelerating finish.
Parameters:
- t: float, time parameter (0-1)
Returns:
float, eased value (0-1)
"""
return 2 * smooth(t / 2.0 + 0.5) - 1
def slow_into(t):
"""
Very slow start, normal finish.
Parameters:
- t: float, time parameter (0-1)
Returns:
float, eased value (0-1)
"""
return np.sqrt(t)
def double_smooth(t):
"""
Double smoothing for extra ease.
Parameters:
- t: float, time parameter (0-1)
Returns:
float, double-smoothed value (0-1)
"""
return smooth(smooth(t))
def there_and_back(t):
"""
Go to 1 and back to 0 (triangle wave).
Parameters:
- t: float, time parameter (0-1)
Returns:
float, triangle wave value (0-1)
"""
return 1 - abs(2*t - 1)
def wiggle(t, wiggles=2):
"""
Oscillating motion.
Parameters:
- t: float, time parameter (0-1)
- wiggles: float, number of oscillations
Returns:
float, oscillating value (0-1)
"""
return there_and_back(t) * np.sin(wiggles * TAU * t)
def overshoot(t):
"""
Overshoot and settle back.
Parameters:
- t: float, time parameter (0-1)
Returns:
float, overshoot curve (0-1)
"""
return smooth(t) * (1 + np.sin(PI * t))
def exponential_decay(t, half_life=0.1):
"""
Exponential decay curve.
Parameters:
- t: float, time parameter (0-1)
- half_life: float, decay rate
Returns:
float, decayed value (0-1)
"""
return np.exp(-t / half_life)
def lingering(t):
"""
Stay near 0, then rush to 1.
Parameters:
- t: float, time parameter (0-1)
Returns:
float, lingering curve (0-1)
"""
return np.clip(smooth(2*t - 1), 0, 1)
def running_start(t, pull_factor=-0.5):
"""
Go backward before moving forward.
Parameters:
- t: float, time parameter (0-1)
- pull_factor: float, how far to pull back
Returns:
float, running start curve
"""
return bezier([0, 0, pull_factor, pull_factor, 1, 1, 1])(t)
def not_quite_there(func=smooth, proportion=0.7):
"""
Modified function that doesn't quite reach 1.
Parameters:
- func: callable, base rate function
- proportion: float, maximum value to reach
Returns:
callable, modified rate function
"""
return lambda t: proportion * func(t)Mathematical operations for 3D vectors and transformations.
def get_norm(vector):
"""
Calculate vector magnitude/length.
Parameters:
- vector: np.array, input vector
Returns:
float, vector magnitude
"""
return np.linalg.norm(vector)
def normalize(vector, fall_back=None):
"""
Normalize vector to unit length.
Parameters:
- vector: np.array, input vector
- fall_back: np.array, fallback if vector is zero
Returns:
np.array, normalized vector
"""
norm = get_norm(vector)
if norm == 0:
return fall_back or np.array([1, 0, 0])
return vector / norm
def cross(v1, v2):
"""
Calculate cross product of two vectors.
Parameters:
- v1: np.array, first vector
- v2: np.array, second vector
Returns:
np.array, cross product vector
"""
return np.cross(v1, v2)
def dot(v1, v2):
"""
Calculate dot product of two vectors.
Parameters:
- v1: np.array, first vector
- v2: np.array, second vector
Returns:
float, dot product
"""
return np.dot(v1, v2)
def angle_between_vectors(v1, v2):
"""
Calculate angle between two vectors.
Parameters:
- v1: np.array, first vector
- v2: np.array, second vector
Returns:
float, angle in radians
"""
cos_angle = dot(normalize(v1), normalize(v2))
return np.arccos(np.clip(cos_angle, -1, 1))
def angle_of_vector(vector):
"""
Calculate angle of vector from positive x-axis.
Parameters:
- vector: np.array, input vector
Returns:
float, angle in radians
"""
return np.arctan2(vector[1], vector[0])
def rotate_vector(vector, angle, axis=OUT):
"""
Rotate vector around specified axis.
Parameters:
- vector: np.array, vector to rotate
- angle: float, rotation angle in radians
- axis: np.array, rotation axis
Returns:
np.array, rotated vector
"""
return np.dot(rotation_matrix(angle, axis), vector)
def rotation_matrix(angle, axis):
"""
Create rotation matrix for axis-angle rotation.
Parameters:
- angle: float, rotation angle in radians
- axis: np.array, rotation axis (will be normalized)
Returns:
np.array, 3x3 rotation matrix
"""
axis = normalize(axis)
cos_angle = np.cos(angle)
sin_angle = np.sin(angle)
return cos_angle * np.eye(3) + \
sin_angle * np.array([[0, -axis[2], axis[1]],
[axis[2], 0, -axis[0]],
[-axis[1], axis[0], 0]]) + \
(1 - cos_angle) * np.outer(axis, axis)
def project_along_vector(point, vector):
"""
Project point onto line defined by vector.
Parameters:
- point: np.array, point to project
- vector: np.array, line direction
Returns:
np.array, projected point
"""
return dot(point, normalize(vector)) * normalize(vector)
def perpendicular_bisector(line_start, line_end):
"""
Find perpendicular bisector of line segment.
Parameters:
- line_start: np.array, line start point
- line_end: np.array, line end point
Returns:
tuple, (midpoint, perpendicular_direction)
"""
midpoint = (line_start + line_end) / 2
direction = line_end - line_start
perp = np.array([-direction[1], direction[0], direction[2]])
return midpoint, normalize(perp)Functions for color manipulation and interpolation.
def color_to_rgba(color, alpha=1):
"""
Convert color to RGBA tuple.
Parameters:
- color: str or tuple, color specification
- alpha: float, opacity (0-1)
Returns:
tuple, (r, g, b, a) values (0-1)
"""
# Implementation handles hex, named colors, RGB tuples
pass
def rgb_to_color(rgb):
"""
Convert RGB tuple to color string.
Parameters:
- rgb: tuple, (r, g, b) values (0-1 or 0-255)
Returns:
str, hex color string
"""
pass
def rgba_to_color(rgba):
"""
Convert RGBA tuple to color (ignoring alpha).
Parameters:
- rgba: tuple, (r, g, b, a) values
Returns:
str, hex color string
"""
pass
def interpolate_color(color1, color2, alpha):
"""
Interpolate between two colors.
Parameters:
- color1: str, first color
- color2: str, second color
- alpha: float, interpolation factor (0-1)
Returns:
str, interpolated color
"""
pass
def average_color(*colors):
"""
Calculate average of multiple colors.
Parameters:
- colors: Color arguments
Returns:
str, averaged color
"""
pass
def invert_color(color):
"""
Invert color (complement).
Parameters:
- color: str, input color
Returns:
str, inverted color
"""
pass
def color_gradient(colors, length):
"""
Create gradient of colors.
Parameters:
- colors: list, colors for gradient
- length: int, number of gradient steps
Returns:
list, gradient colors
"""
passUtilities for file handling and path management.
def guarantee_existence(path):
"""
Ensure directory exists, create if necessary.
Parameters:
- path: str, directory path
Returns:
str, normalized path
"""
pass
def get_full_raster_image_path(image_file_name):
"""
Get full path to raster image file.
Parameters:
- image_file_name: str, image filename
Returns:
str, full path to image
"""
pass
def get_full_vector_image_path(vector_file_name):
"""
Get full path to vector image file.
Parameters:
- vector_file_name: str, vector filename
Returns:
str, full path to vector file
"""
pass
def get_directories():
"""
Get standard ManimGL directories.
Returns:
dict, directory paths
"""
passTools for development, debugging, and performance analysis.
def get_time_progression(run_time, n_iterations, dt):
"""
Generate time progression for animations.
Parameters:
- run_time: float, total animation time
- n_iterations: int, number of steps
- dt: float, time step
Returns:
np.array, time values
"""
pass
def binary_search(function, target, lower_bound, upper_bound, tolerance=1e-4):
"""
Binary search for function root.
Parameters:
- function: callable, function to search
- target: float, target value
- lower_bound: float, search lower bound
- upper_bound: float, search upper bound
- tolerance: float, convergence tolerance
Returns:
float, found root
"""
pass
class DebugTeX:
"""
Debugging utilities for LaTeX rendering.
"""
@staticmethod
def debug_tex(tex_string):
"""Debug LaTeX compilation issues."""
pass
class PerformanceTimer:
"""
Context manager for timing code execution.
"""
def __enter__(self):
pass
def __exit__(self, *args):
passfrom manimgl import *
class ConstantsExample(Scene):
def construct(self):
# Using directional constants
circle = Circle().shift(UP * 2 + RIGHT * 3)
# Using color constants
square = Square(color=BLUE_B).shift(DOWN * 2)
# Using mathematical constants
arc = Arc(angle=PI/3, radius=2, color=YELLOW)
self.add(circle, square, arc)
self.wait()class RateFunctionExample(Scene):
def construct(self):
square = Square()
# Use different rate functions
self.play(square.animate.shift(UP), rate_func=smooth)
self.play(square.animate.shift(RIGHT), rate_func=rush_into)
self.play(square.animate.shift(DOWN), rate_func=there_and_back)
self.play(square.animate.shift(LEFT), rate_func=wiggle)
self.wait()class VectorExample(Scene):
def construct(self):
# Create vectors
v1 = np.array([2, 1, 0])
v2 = np.array([1, 2, 0])
# Vector operations
v1_norm = normalize(v1)
cross_product = cross(v1, v2)
angle = angle_between_vectors(v1, v2)
# Visualize results
arrow1 = Arrow(ORIGIN, v1, color=RED)
arrow2 = Arrow(ORIGIN, v2, color=BLUE)
arrow3 = Arrow(ORIGIN, cross_product, color=GREEN)
angle_text = Text(f"Angle: {angle:.2f} rad").to_edge(UP)
self.add(arrow1, arrow2, arrow3, angle_text)
self.wait()class ColorExample(Scene):
def construct(self):
circles = VGroup(*[
Circle(radius=0.5).shift(i*RIGHT - 3*RIGHT)
for i in range(7)
])
# Interpolate between colors
for i, circle in enumerate(circles):
alpha = i / (len(circles) - 1)
color = interpolate_color(RED, BLUE, alpha)
circle.set_color(color)
self.add(circles)
self.wait()class FileExample(Scene):
def construct(self):
# Ensure output directory exists
output_dir = "./my_animations"
guarantee_existence(output_dir)
# Load image
image_path = get_full_raster_image_path("my_image.png")
text = Text("File operations complete")
self.add(text)
self.wait()Install with Tessl CLI
npx tessl i tessl/pypi-manimgldocs