Importing From Manim¶
Algan supports all of the same Mobjects that Manim does
Manim’s, implemented as native Algan mobs.
If you prefer, you can also create Mobjects using Manim
and then import them to Algan using ManimMob.
Manim is a dependency of Algan, so import manim works out of the box; there
is nothing extra to install.
Note
You can import Manim objects (geometry), but not Manim animations.
Manim’s Transform, Create, and FadeIn don’t exist on Algan’s
timeline. Instead, animate the imported Mobs using Algan’s own animation
methods and contexts.
The ManimMob¶
Wrap any Manim Mobject in ManimMob to turn it into an Algan Mob:
Example: ImportingManimMob ¶
from algan import *
import manim as mn
# Let's grab a complex plane from the Manim library.
plane = ManimMob(mn.ComplexPlane().add_coordinates()).spawn()
# Now we have a Mob we can animate with Algan.
with Seq(runtime=5):
plane.scale(0.5)
plane.rotate(90, OUT)
Scene.save_video()
Important
Do not use both from algan import * and from manim import * in the
same file, as many class names clash. Import Manim under an alias (like
import manim as mn).
Plotting Functions on Axes¶
Graphing is the usual reason to reach for Manim’s geometry, and it needs no
wrapping at all: Axes is available under its own name, and what
Axes.plot hands back is an ordinary Algan Mob that you spawn and animate
like any other.
Example: ImportingManimPlot ¶
from algan import *
import numpy as np
axes = Axes(x_range=(-3, 3, 1), y_range=(-1.5, 1.5, 0.5), x_length=9, y_length=4.5)
# plot() returns a Mob of its own -- spawn it like any other.
graph = axes.plot(lambda x: np.sin(x), color=YELLOW)
with Off():
axes.spawn()
graph.spawn()
with Seq(runtime=2):
graph.rotate(20, UP)
graph.rotate(-20, UP)
Scene.save_video()
Helper methods like plot_parametric_curve, get_axis_labels, and
get_graph_label work the same way: they return Mobs that you can spawn and
animate independently.
Importing a finished Manim diagram¶
When you would rather assemble the whole thing in Manim, build it there,
collect it into a single VGroup, and wrap that group once:
Example: ImportingManimVGroup ¶
from algan import *
import manim as mn
import numpy as np
diagram = mn.VGroup()
axes = mn.Axes(x_range=(-3, 3, 1), y_range=(-1.5, 1.5, 0.5), x_length=9, y_length=4.5)
diagram.add(axes, axes.plot(lambda x: np.sin(x), color=mn.YELLOW))
plot = ManimMob(diagram).spawn()
plot.scale(0.7)
Scene.save_video()
Wrapping the finished VGroup gives you one Algan Mob whose parts are its
children, so you can animate the whole diagram together or reach into
plot.children for an individual piece.
3-D Manim Geometry¶
Manim’s 3-D Mobjects import too, and they arrive as real 3-D geometry rather
than as something flattened to face you. A Surface (and everything
built on it e.g. Sphere, Torus, Cone) is a grid of curved quad tiles
in Manim, and each tile becomes one of the same curved patches Algan’s own
3-D shapes are made of: it is diced to triangles afresh in every frame, as
finely as that frame needs and no more, so the silhouette stays smooth however
far you push the camera in.
Example: ImportingManim3D ¶
from algan import *
import manim as mn
import numpy as np
with Off():
ball = ManimMob(mn.Sphere(resolution=(16, 8)))
coil = ManimMob(mn.ParametricFunction(
lambda t: np.array([1.8 * np.cos(t), 1.8 * np.sin(t), t / 3 - 3.1]),
t_range=[0, 6 * np.pi], stroke_width=8,
))
# Manim builds both around its own z axis, which is Algan's OUT --
# straight at the camera; stand them upright before animating.
Group(ball, coil).rotate(-75, RIGHT).spawn()
with Sync(runtime=4):
ball.rotate(360, UP)
coil.rotate(360, UP)
Scene.save_video()
Importing an SVG¶
An .svg file drawn in Inkscape, Illustrator or Figma comes in through the
same door. SVGMob parses the file into cubic Bezier outlines,
which is exactly what Algan’s 2-D shapes are made of, so the result is a
first-class Mob: it scales without pixelating, takes Algan colors, and morphs
into other shapes:
from algan import *
logo = SVGMob("logo.svg").scale(2).spawn()
logo.color = BLUE
logo.rotate(360, UP)
Scene.save_video()
Each path in the file becomes its own Mob inside the result, reachable through
children (the top-level Mob holds a
Group, whose children are the paths), so you can animate an individual
piece without disturbing the rest. Unlike a Group, an
SVGMob is not itself indexable.
The path is resolved by Manim, which looks for it relative to the working
directory rather than to your script. So unlike ImageMob, launching
Python from a different directory can lose an SVG that sits beside your .py
file. Pass an absolute path if that matters.
Only path geometry is imported. Embedded raster images, filters, gradients and text-as-text do not survive the conversion. Convert text to outlines in your editor before exporting.
Colors and Coordinates¶
The two libraries use different conventions, and the boundary is the
ManimMob constructor:
Colors. Inside Manim code use Manim’s colors (
mn.YELLOW); once the Mob is an Algan Mob, use Algan’s (YELLOW).Coordinates. The two agree throughout:
UP,RIGHTandOUTmean the same directions and the same signs on both sides, so an imported point keeps the coordinates it was written with.Sizes. Manim’s default frame is 8 units tall; Algan’s visible area at the origin plane is about 7. Imported diagrams usually want a modest
scale()orfit_to_screen().
Matching Manim’s framing exactly¶
Rather than rescaling each import, you can point the whole Scene at Manim’s own
defaults with Scene.use_manim_defaults().
Call it once, before you build anything, and imported geometry lands on the
pixels Manim would have put it on: same 8-unit frame height, same perspective,
same light position, same black background. The two engines’ axes already
agree, so nothing is converted on the way in.
from algan import *
import manim as mn
Scene.use_manim_defaults()
square = ManimMob(mn.Square(color=mn.BLUE)).spawn()
square.move(RIGHT)
Scene.save_video()
Matching Manim’s defaults in the Manim Migration Guide is the full treatment: what each of the four parts takes from Manim, how to decline one, and the two extras that are off by default.
How close it gets¶
Close enough that the two are hard to tell apart, but not byte-identical, and the residue is worth knowing:
Flat fills are exact. A filled region renders to the same bytes as Manim’s.
Unfilled strokes land within about a third of a pixel at 854x480.
A filled shape’s outline is offset by half its stroke width. Manim centres a stroke on the path; Algan draws a filled circuit’s border inside it. At Manim’s default
stroke_widthof 4 that is about 1 pixel at 854x480.3-D solids are shaded differently. Manim shades a face by a two-point gradient across it (
shading_factor0.2); Algan ray-traces. Silhouettes, positions and base colors agree, the shading within a face does not.
Native Compatibility Classes¶
For convenience, Algan also exposes many of Manim’s composite Mobjects under
their own names, so they can be constructed without touching manim:
Axes, NumberPlane, NumberLine,
BarChart, Table, Brace, Graph,
Arc, Annulus, Ellipse, Star,
Arrow and more.
They keep their Manim constructor arguments and methods, and are Algan Mobs in
every other respect: Algan’s positioning, sizing and animation methods all work
on them, and their sizes can equally be set through their own Manim keyword
arguments (x_length, y_length).
Example: ImportingCompatClasses ¶
from algan import *
plane = NumberPlane().scale(0.7).spawn()
plane.rotate(30, UP)
Scene.save_video()
See Also¶
Manim Migration Guide – the full concept-by-concept mapping, if you are porting a Manim project.
The Mob Gallery – which of these classes are available under their own names, alongside Algan’s native shapes.
Importing 3-D Models – importing
.glb/.fbxmodels rather than Manim geometry.Shaders and Materials – giving imported geometry an Algan material.
Reference Manual – the full API reference.