Created
November 3, 2024 04:32
-
-
Save bmorphism/0b82ada6b6f0ae9d79426769c14c6dd6 to your computer and use it in GitHub Desktop.
txt2world
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from manim import * | |
from manim.utils.space_ops import rotate_vector | |
from manim.utils.color import interpolate_color | |
import numpy as np | |
class CreateCircle(Scene): | |
def construct(self): | |
circle = Circle() # create a circle | |
circle.set_fill(PINK, opacity=0.5) # set the color and transparency | |
self.play(Create(circle)) # show the circle on screen | |
class SquareToCircle(Scene): | |
def construct(self): | |
circle = Circle() # create a circle | |
circle.set_fill(PINK, opacity=0.5) # set color and transparency | |
square = Square() # create a square | |
square.rotate(PI / 4) # rotate a certain amount | |
self.play(Create(square)) # animate the creation of the square | |
self.play(Transform(square, circle)) # interpolate the square into the circle | |
self.play(FadeOut(square)) # fade out animation | |
class SquareAndCircle(Scene): | |
def construct(self): | |
circle = Circle() # create a circle | |
circle.set_fill(PINK, opacity=0.5) # set the color and transparency | |
square = Square() # create a square | |
square.set_fill(BLUE, opacity=0.5) # set the color and transparency | |
square.next_to(circle, RIGHT, buff=0.5) # set the position | |
self.play(Create(circle), Create(square)) # show the shapes on screen | |
class HolographicPrinciple(Scene): | |
def construct(self): | |
def fractal_tree(start_point, direction, length, depth): | |
if depth == 0 or length < 0.05: | |
return VGroup() | |
end_point = start_point + length * direction | |
line = Line(start_point, end_point, color=GREEN) | |
left_branch = fractal_tree( | |
end_point, | |
rotate_vector(direction, PI / 6), | |
length * 0.67, | |
depth - 1 | |
) | |
right_branch = fractal_tree( | |
end_point, | |
rotate_vector(direction, -PI / 6), | |
length * 0.67, | |
depth - 1 | |
) | |
return VGroup(line, left_branch, right_branch) | |
tree = fractal_tree(ORIGIN + DOWN * 3, UP, 1.5, 8) | |
self.play(Create(tree)) | |
self.wait() | |
class YoYo(Scene): | |
def construct(self): | |
# Create the yoyo (a circle) and the string | |
yoyo_radius = 0.3 | |
yoyo = Circle(radius=yoyo_radius, color=RED, fill_opacity=1) | |
yoyo_initial_position = UP * 2 | |
yoyo.move_to(yoyo_initial_position) | |
string = Line(ORIGIN, yoyo.get_center(), color=WHITE) | |
self.add(string, yoyo) | |
# Define the path for the yoyo to move along | |
yoyo_path = Line(yoyo_initial_position, DOWN * 2) | |
# Updater to keep the string connected to the yoyo | |
def update_string(mob): | |
new_string = Line(ORIGIN, yoyo.get_center(), color=WHITE) | |
mob.become(new_string) | |
string.add_updater(update_string) | |
# Animate the yoyo going down and up repeatedly | |
self.play( | |
MoveAlongPath(yoyo, yoyo_path, rate_func=linear), | |
run_time=2 | |
) | |
self.play( | |
MoveAlongPath(yoyo, yoyo_path, rate_func=lambda t: 1 - t), | |
run_time=2 | |
) | |
self.wait() | |
# Remove the updater when done | |
string.remove_updater(update_string) | |
class FoldingSierpinski(ThreeDScene): | |
def construct(self): | |
# Create the initial triangle vertices | |
p1 = LEFT * 4 + DOWN * 2 | |
p2 = RIGHT * 4 + DOWN * 2 | |
p3 = UP * 4 + DOWN * 2 | |
vertices = [p1, p2, p3] | |
# Function to create the Sierpinski triangle recursively | |
def sierpinski(order, vertices): | |
if order == 0: | |
triangle = Polygon( | |
*vertices, | |
fill_color=WHITE, | |
fill_opacity=1, | |
stroke_color=BLACK, | |
stroke_width=0.5 | |
) | |
return triangle | |
else: | |
# Calculate midpoints of the sides | |
midpoints = [ | |
(vertices[0] + vertices[1]) / 2, | |
(vertices[1] + vertices[2]) / 2, | |
(vertices[2] + vertices[0]) / 2 | |
] | |
# Recursively create smaller triangles | |
return VGroup( | |
sierpinski(order - 1, [vertices[0], midpoints[0], midpoints[2]]), | |
sierpinski(order - 1, [midpoints[0], vertices[1], midpoints[1]]), | |
sierpinski(order - 1, [midpoints[2], midpoints[1], vertices[2]]) | |
) | |
# Create the Sierpinski triangle of order 4 | |
order = 4 | |
sierpinski_triangle = sierpinski(order, vertices) | |
sierpinski_triangle.set_style(stroke_width=0) | |
sierpinski_triangle.set_color_by_gradient(BLUE, GREEN, YELLOW, RED) | |
self.add(sierpinski_triangle) | |
self.wait(1) | |
# Set up the camera | |
self.set_camera_orientation(phi=75 * DEGREES, theta=-45 * DEGREES) | |
# Level 1 triangles for folding | |
# Compute midpoints | |
midpoints = [ | |
(vertices[0] + vertices[1]) / 2, | |
(vertices[1] + vertices[2]) / 2, | |
(vertices[2] + vertices[0]) / 2 | |
] | |
# Create the outer triangles and the central triangle | |
t_outer = [ | |
Polygon(vertices[0], midpoints[0], midpoints[2], fill_color=BLUE_E, fill_opacity=1, stroke_width=0.5), | |
Polygon(vertices[1], midpoints[1], midpoints[0], fill_color=GREEN_E, fill_opacity=1, stroke_width=0.5), | |
Polygon(vertices[2], midpoints[2], midpoints[1], fill_color=RED_E, fill_opacity=1, stroke_width=0.5) | |
] | |
t_center = Polygon(midpoints[0], midpoints[1], midpoints[2], fill_color=YELLOW_E, fill_opacity=1, stroke_width=0.5) | |
# Add the triangles to the scene | |
self.add(t_center, *t_outer) | |
self.wait(1) | |
# Remove the large Sierpinski triangle | |
self.remove(sierpinski_triangle) | |
# Define fold axes and points | |
fold_animations = [] | |
fold_axes = [] | |
about_points = [] | |
for i in range(3): | |
# Edge of the central triangle corresponding to the fold | |
start = midpoints[i] | |
end = midpoints[(i + 1) % 3] | |
edge_vector = end - start | |
# Fold axis is perpendicular to the edge, pointing out of the plane | |
fold_axis = np.cross(edge_vector, OUT) | |
fold_axis = normalize(fold_axis) | |
# The fold happens about the edge of the central triangle | |
about_point = start | |
# Save axis and point for unfolding | |
fold_axes.append(fold_axis) | |
about_points.append(about_point) | |
# Create folding animation | |
fold_animations.append( | |
Rotate( | |
t_outer[i], | |
angle=PI, | |
axis=fold_axis, | |
about_point=about_point, | |
run_time=2 | |
) | |
) | |
# Play the folding animations | |
self.play(*fold_animations) | |
self.wait(2) | |
# Unfolding animations (reverse the folding) | |
unfold_animations = [] | |
for i in range(3): | |
unfold_animations.append( | |
Rotate( | |
t_outer[i], | |
angle=-PI, | |
axis=fold_axes[i], | |
about_point=about_points[i], | |
run_time=2 | |
) | |
) | |
self.play(*unfold_animations) | |
self.wait(2) | |
# Rotate the camera to showcase the 3D effect | |
self.begin_ambient_camera_rotation(rate=0.2) | |
self.wait(5) | |
self.stop_ambient_camera_rotation() | |
self.wait(2) | |
from manim import * | |
import numpy as np | |
class FoucaultPendulum(ThreeDScene): | |
def construct(self): | |
# Set up camera orientation | |
self.set_camera_orientation(phi=75 * DEGREES, theta=30 * DEGREES) | |
# Pendulum parameters | |
length = 5 # Length of the pendulum | |
g = 9.8 # Acceleration due to gravity | |
omega = np.sqrt(g / length) # Angular frequency | |
rotation_rate = 0.1 # Rotation rate simulating Earth's rotation | |
# Create pivot point | |
pivot = Dot3D(ORIGIN, color=WHITE) | |
self.add(pivot) | |
# Create pendulum bob | |
bob_radius = 0.2 | |
bob = Sphere(radius=bob_radius, color=RED).move_to([0, -length, 0]) | |
# Create rod | |
rod = Line3D(pivot.get_center(), bob.get_center(), color=WHITE) | |
# Group bob and rod | |
pendulum = VGroup(rod, bob) | |
self.add(pendulum) | |
# Create a reference circle (floor) | |
floor_radius = 3 | |
floor = Circle(radius=floor_radius, color=GRAY) | |
floor.rotate(PI/2, axis=RIGHT) | |
floor.shift(DOWN * length) | |
self.add(floor) | |
# Add markers on the floor to show rotation | |
for angle in np.linspace(0, 2 * PI, 12, endpoint=False): | |
marker = Line(ORIGIN, RIGHT * 0.1, color=YELLOW) | |
marker.rotate(angle, axis=UP) | |
marker.shift([floor_radius * np.cos(angle), -length, floor_radius * np.sin(angle)]) | |
self.add(marker) | |
# Initialize time for updater | |
pendulum.time = 0 | |
# Animation updater | |
def update_pendulum(mob, dt): | |
mob.time += dt | |
angle = 0.2 * np.cos(omega * mob.time) | |
rotation = rotation_rate * mob.time | |
x = length * np.sin(angle) * np.cos(rotation) | |
y = -length * np.cos(angle) | |
z = length * np.sin(angle) * np.sin(rotation) | |
bob_position = np.array([x, y, z]) | |
rod.put_start_and_end_on(pivot.get_center(), bob_position) | |
bob.move_to(bob_position) | |
pendulum.add_updater(update_pendulum) | |
# Ambient camera rotation for better visualization | |
self.begin_ambient_camera_rotation(rate=0.05) | |
# Run the animation | |
self.wait(20) | |
# Clean up | |
pendulum.remove_updater(update_pendulum) | |
self.stop_ambient_camera_rotation() | |
self.wait() | |
from manim import * | |
import numpy as np | |
class TropicalDerangementVisualization(Scene): | |
def construct(self): | |
# Display tropical operations using Text instead of MathTex | |
add_text = Text("Tropical Addition: a ⊕ b = min(a, b)", font_size=24).to_edge(UP) | |
mul_text = Text("Tropical Multiplication: a ⊗ b = a + b", font_size=24).next_to(add_text, DOWN) | |
self.play(Write(add_text), Write(mul_text)) | |
self.wait(1) | |
# Create axes for tropical lines | |
axes = Axes( | |
x_range=[0, 6, 1], | |
y_range=[0, 6, 1], | |
x_length=6, | |
y_length=6, | |
axis_config={"include_numbers": True}, | |
).shift(DOWN * 0.5) | |
axis_labels = axes.get_axis_labels(x_label="a", y_label="b") | |
self.play(Create(axes), Write(axis_labels)) | |
self.wait(1) | |
# Plot tropical lines y = min(x, c) | |
c_values = [2, 4] | |
lines = VGroup() | |
colors = [BLUE, GREEN] | |
for c, color in zip(c_values, colors): | |
line = axes.plot_line_graph( | |
x_values=[0, c, 6], | |
y_values=[c, c, 6], | |
line_color=color | |
) | |
lines.add(line) | |
self.play(Create(lines)) | |
self.wait(1) | |
# Visualize derangement | |
elements = ['1', '2', '3', '4'] | |
positions = [LEFT * 3 + DOWN * 2, LEFT + DOWN * 2, RIGHT + DOWN * 2, RIGHT * 3 + DOWN * 2] | |
circles = VGroup(*[Circle(radius=0.5, color=WHITE).move_to(pos) for pos in positions]) | |
labels = VGroup(*[Text(str(e), font_size=24).move_to(pos) for e, pos in zip(elements, positions)]) | |
self.play(Create(circles), Write(labels)) | |
self.wait(1) | |
# Derangement mapping | |
mapping = [2, 3, 4, 1] # A derangement permutation | |
arrows = VGroup() | |
for i, m in enumerate(mapping): | |
arrow = Arrow( | |
start=circles[i].get_right(), | |
end=circles[m - 1].get_right(), | |
buff=0.5, | |
color=YELLOW, | |
max_tip_length_to_length_ratio=0.1 | |
) | |
arrows.add(arrow) | |
self.play(Create(arrows)) | |
self.wait(1) | |
# Inverse derangement mapping | |
inverse_mapping = [4, 1, 2, 3] | |
inverse_arrows = VGroup() | |
for i, m in enumerate(inverse_mapping): | |
arrow = Arrow( | |
start=circles[i].get_left(), | |
end=circles[m - 1].get_left(), | |
buff=0.5, | |
color=RED, | |
max_tip_length_to_length_ratio=0.1 | |
) | |
inverse_arrows.add(arrow) | |
self.play(Create(inverse_arrows)) | |
self.wait(1) | |
# Transition to topological space visualization | |
self.play( | |
FadeOut(VGroup(add_text, mul_text, axes, axis_labels, lines, circles, labels, arrows, inverse_arrows)) | |
) | |
self.wait(1) | |
# Visualize topological space (Torus) | |
torus = Torus(major_radius=2, minor_radius=0.7, color=GREY_BROWN) | |
torus.rotate(PI / 2, axis=RIGHT) | |
self.play(Create(torus)) | |
self.wait(1) | |
# Animate path representing behaviors | |
dot = Dot(point=torus.point_at_angle(0), color=TEAL_A) | |
self.add(dot) | |
def update_dot(mob, dt): | |
mob.angle = (mob.angle + dt) % TAU | |
new_point = torus.point_at_angle(mob.angle) | |
mob.move_to(new_point) | |
dot.angle = 0 | |
dot.add_updater(update_dot) | |
self.wait(10) | |
dot.remove_updater(update_dot) | |
self.wait(2) | |
from manim import * | |
import numpy as np | |
class MobiusStrip(ThreeDScene): | |
def construct(self): | |
# Set up camera orientation | |
self.set_camera_orientation(phi=75 * DEGREES, theta=30 * DEGREES) | |
# Parameters for the Möbius strip | |
radius = 2 # Radius of the central circle | |
width = 1 # Width of the strip | |
turns = 1 # Number of half-twists (1 for a standard Möbius strip) | |
# Create the Möbius strip | |
mobius = Surface( | |
lambda u, v: self.mobius_surface(u, v, radius, width, turns), | |
u_range=[0, TAU], | |
v_range=[-width / 2, width / 2], | |
checkerboard_colors=[BLUE_E, BLUE_D], | |
resolution=(50, 8) | |
) | |
# Add the Möbius strip to the scene | |
self.play(Create(mobius)) | |
self.wait(1) | |
# Rotate the Möbius strip for visualization | |
self.play(Rotate(mobius, angle=TAU, axis=OUT), run_time=5) | |
self.wait(1) | |
def mobius_surface(self, u, v, radius, width, turns): | |
# Möbius strip parameterization | |
# u: angle around the circle | |
# v: position across the width of the strip | |
twist = turns * u / 2 # Controls the half-twist | |
x = (radius + v * np.cos(twist)) * np.cos(u) | |
y = (radius + v * np.cos(twist)) * np.sin(u) | |
z = v * np.sin(twist) | |
return np.array([x, y, z]) | |
class TesseractProjection(ThreeDScene): | |
def construct(self): | |
# Set up camera orientation | |
self.set_camera_orientation(phi=75 * DEGREES, theta=45 * DEGREES) | |
# Parameters for the tesseract | |
size = 2 # Size of the hypercube | |
# Generate the vertices of a tesseract in 4D space | |
vertices_4d = [] | |
for i in range(16): | |
x = size * (1 if i & 1 else -1) | |
y = size * (1 if i & 2 else -1) | |
z = size * (1 if i & 4 else -1) | |
w = size * (1 if i & 8 else -1) | |
vertices_4d.append([x, y, z, w]) | |
# Project the 4D vertices into 3D space | |
projected_vertices = [] | |
for v in vertices_4d: | |
# Perspective projection from 4D to 3D | |
d = 5 # Distance from viewer to the hypercube | |
w = v[3] | |
projection_factor = d / (d - w) | |
x = v[0] * projection_factor | |
y = v[1] * projection_factor | |
z = v[2] * projection_factor | |
projected_vertices.append([x, y, z]) | |
# Create lines between vertices that are connected in 4D space | |
edges = [] | |
for i in range(16): | |
for j in range(i + 1, 16): | |
# In 4D, vertices are connected if they differ by one coordinate | |
if bin(i ^ j).count('1') == 1: | |
start = projected_vertices[i] | |
end = projected_vertices[j] | |
edge = Line3D( | |
start=np.array(start), | |
end=np.array(end), | |
color=BLUE, | |
stroke_width=2, | |
) | |
edges.append(edge) | |
# Group all edges | |
tesseract = VGroup(*edges) | |
# Add axes for reference | |
axes = ThreeDAxes() | |
self.add(axes) | |
# Add the tesseract to the scene | |
self.play(Create(tesseract)) | |
self.wait(1) | |
# Animate rotation of the tesseract | |
self.play( | |
Rotate(tesseract, angle=TAU, axis=OUT + RIGHT, run_time=8, rate_func=smooth) | |
) | |
self.wait(2) | |
from manim import * | |
import numpy as np | |
class ColoredTesseractProjection(ThreeDScene): | |
def construct(self): | |
# Set up camera orientation | |
self.set_camera_orientation(phi=75 * DEGREES, theta=45 * DEGREES) | |
# Parameters for the tesseract | |
size = 2 # Size of the hypercube | |
# Generate the vertices of a tesseract in 4D space | |
vertices_4d = [] | |
for i in range(16): | |
x = size * (1 if i & 1 else -1) | |
y = size * (1 if i & 2 else -1) | |
z = size * (1 if i & 4 else -1) | |
w = size * (1 if i & 8 else -1) | |
vertices_4d.append([x, y, z, w]) | |
# Project the 4D vertices into 3D space | |
projected_vertices = [] | |
for v in vertices_4d: | |
# Perspective projection from 4D to 3D | |
d = 5 # Distance from viewer to the hypercube | |
w_coord = v[3] | |
projection_factor = d / (d - w_coord) | |
x = v[0] * projection_factor | |
y = v[1] * projection_factor | |
z = v[2] * projection_factor | |
projected_vertices.append([x, y, z]) | |
# Create edges with coloring based on self-reflexive property | |
edges = VGroup() | |
for i in range(16): | |
for j in range(i + 1, 16): | |
# In 4D, vertices are connected if they differ by one coordinate | |
hamming_distance = bin(i ^ j).count('1') | |
if hamming_distance == 1: | |
start = projected_vertices[i] | |
end = projected_vertices[j] | |
# Assign color based on the coordinate that differs | |
differing_coordinate = int(np.log2(i ^ j)) | |
if differing_coordinate == 0: | |
color = RED # x-coordinate differs | |
elif differing_coordinate == 1: | |
color = GREEN # y-coordinate differs | |
elif differing_coordinate == 2: | |
color = BLUE # z-coordinate differs | |
elif differing_coordinate == 3: | |
color = YELLOW # w-coordinate differs | |
edge = Line3D( | |
start=np.array(start), | |
end=np.array(end), | |
color=color, | |
stroke_width=2, | |
) | |
edges.add(edge) | |
# Add axes for reference | |
axes = ThreeDAxes() | |
self.add(axes) | |
# Add the tesseract edges to the scene | |
self.play(Create(edges)) | |
self.wait(1) | |
# Animate rotation of the tesseract | |
self.play( | |
Rotate(edges, angle=TAU, axis=OUT + RIGHT, run_time=8, rate_func=smooth) | |
) | |
self.wait(2) | |
from manim import * | |
import numpy as np | |
class FiveDMobiusStrip(ThreeDScene): | |
def construct(self): | |
# Set up camera orientation | |
self.set_camera_orientation(phi=70 * DEGREES, theta=45 * DEGREES) | |
# Parameters for the Möbius strip | |
radius = 2 # Radius of the central circle | |
width = 1 # Width of the strip | |
twists = 1 # Number of half-twists | |
# Additional parameters to simulate higher dimensions | |
def five_d_mobius(u, v): | |
# Möbius strip parameterization extended to simulate higher dimensions | |
# u: angle around the central circle | |
# v: position across the width of the strip | |
# Simulating higher dimensions using extra sine and cosine functions | |
a = np.sin(2 * u + v) | |
b = np.cos(3 * u - v) | |
x = (radius + width * v * np.cos(twists * u / 2)) * np.cos(u) + 0.2 * a | |
y = (radius + width * v * np.cos(twists * u / 2)) * np.sin(u) + 0.2 * b | |
z = width * v * np.sin(twists * u / 2) + 0.2 * a * b | |
return np.array([x, y, z]) | |
# Create the Möbius strip | |
mobius = Surface( | |
five_d_mobius, | |
u_range=[0, TAU], | |
v_range=[-1, 1], | |
resolution=(60, 16), | |
) | |
# Apply color mapping to simulate higher dimensions | |
mobius.set_color_by_rgb_function( | |
lambda x, y, z: ( | |
0.5 * np.cos(2 * x) + 0.5, | |
0.5 * np.cos(2 * y) + 0.5, | |
0.5 * np.cos(2 * z) + 0.5 | |
) | |
) | |
# Add the Möbius strip to the scene | |
self.add(mobius) | |
self.play(Create(mobius), run_time=3) | |
self.wait(1) | |
# Rotate the Möbius strip for visualization | |
self.play( | |
Rotate(mobius, angle=TAU, axis=OUT + RIGHT, run_time=8, rate_func=smooth) | |
) | |
self.wait(2) | |
from manim import * | |
import numpy as np | |
class AceToMobius(ThreeDScene): | |
def construct(self): | |
# Create the Ace of Spades using LaTeX | |
ace_of_spades = MathTex(r"A\spadesuit") | |
ace_of_spades.set_color(BLACK) | |
ace_of_spades.scale(3) | |
ace_of_spades.shift(UP * 0.5) | |
# Create the Möbius strip | |
mobius_strip = ParametricSurface( | |
self.mobius_function, | |
u_range=[0, TAU], | |
v_range=[-1, 1], | |
resolution=(50, 16), | |
checkerboard_colors=[GREY_BROWN, GREY_BROWN], | |
fill_opacity=1 | |
) | |
mobius_strip.set_color(BLACK) | |
mobius_strip.scale(2) | |
# Set up the camera for 3D visualization | |
self.set_camera_orientation(phi=75 * DEGREES, theta=30 * DEGREES) | |
# Display the Ace of Spades | |
self.play(FadeIn(ace_of_spades)) | |
self.wait(1) | |
# Transform the Ace into the Möbius strip | |
self.play(Transform(ace_of_spades, mobius_strip), run_time=4) | |
self.wait(1) | |
# Rotate the Möbius strip to showcase it | |
self.begin_ambient_camera_rotation(rate=0.2) | |
self.wait(5) | |
self.stop_ambient_camera_rotation() | |
self.wait(2) | |
def mobius_function(self, u, v): | |
# Möbius strip parameterization | |
x = (1 + 0.5 * v * np.cos(u / 2)) * np.cos(u) | |
y = (1 + 0.5 * v * np.cos(u / 2)) * np.sin(u) | |
z = 0.5 * v * np.sin(u / 2) | |
return np.array([x, y, z]) | |
from manim import * | |
import numpy as np | |
class ColorfulBlochSphere(ThreeDScene): | |
def construct(self): | |
# Create the Bloch sphere | |
sphere = Sphere(radius=2, resolution=(50, 50)) | |
sphere.set_fill(opacity=1) | |
sphere.set_color_by_gradient(RED, ORANGE, YELLOW, GREEN, BLUE, PURPLE) | |
sphere.set_stroke(color=WHITE, width=0.5) | |
# Create longitude and latitude lines | |
longitude_lines = VGroup() | |
latitude_lines = VGroup() | |
num_longitude = 24 | |
num_latitude = 12 | |
for i in range(num_longitude): | |
theta = TAU * i / num_longitude | |
lon_line = ParametricFunction( | |
lambda t: np.array([ | |
2 * np.cos(t) * np.sin(theta), | |
2 * np.sin(t) * np.sin(theta), | |
2 * np.cos(theta) | |
]), | |
t_range=[0, TAU], | |
color=GREY_B, | |
stroke_width=0.5 | |
) | |
longitude_lines.add(lon_line) | |
for i in range(1, num_latitude): | |
phi = PI * i / num_latitude | |
radius = 2 * np.sin(phi) | |
z = 2 * np.cos(phi) | |
lat_circle = Circle(radius=radius, color=GREY_B, stroke_width=0.5) | |
lat_circle.shift(z * OUT) | |
lat_circle.rotate(angle=90 * DEGREES, axis=RIGHT) | |
latitude_lines.add(lat_circle) | |
# Create axes | |
axes = ThreeDAxes( | |
x_range=[-2, 2, 1], | |
y_range=[-2, 2, 1], | |
z_range=[-2, 2, 1], | |
x_length=4, | |
y_length=4, | |
z_length=4, | |
) | |
# Label axes using Text instead of Tex | |
x_label = Text("X", color=RED).move_to([2.5, 0, 0]) | |
y_label = Text("Y", color=GREEN).move_to([0, 2.5, 0]) | |
z_label = Text("Z", color=BLUE).move_to([0, 0, 2.5]) | |
labels = VGroup(x_label, y_label, z_label) | |
# Create a state vector | |
theta_angle = PI / 3 # Polar angle | |
phi_angle = PI / 4 # Azimuthal angle | |
vector = Arrow3D( | |
start=ORIGIN, | |
end=[ | |
2 * np.sin(theta_angle) * np.cos(phi_angle), | |
2 * np.sin(theta_angle) * np.sin(phi_angle), | |
2 * np.cos(theta_angle) | |
], | |
color=YELLOW, | |
thickness=0.05, | |
) | |
# Animate the state vector rotating around the Bloch sphere | |
vector.rotate_about_origin(PI / 4) | |
# Set up camera | |
self.set_camera_orientation(phi=75 * DEGREES, theta=30 * DEGREES) | |
# Add all elements to the scene | |
self.add(axes, labels) | |
self.add(sphere) | |
self.add(longitude_lines, latitude_lines) | |
self.add(vector) | |
# Rotate the camera around the sphere | |
self.begin_ambient_camera_rotation(rate=0.1) | |
# Rotate the vector around the sphere | |
self.play(Rotate(vector, angle=TAU, axis=UP, about_point=ORIGIN, run_time=8, rate_func=linear)) | |
self.wait() | |
from manim import * | |
import numpy as np | |
class ComplexSurfaces(ThreeDScene): | |
def construct(self): | |
# Set up the camera | |
self.set_camera_orientation(phi=60 * DEGREES, theta=-45 * DEGREES) | |
# Create the Kummer Surface approximation | |
kummer = self.create_kummer_surface() | |
kummer.set_color_by_gradient(BLUE, PURPLE) | |
kummer.scale(1.5) | |
# Create the Clebsch Diagonal Cubic approximation | |
clebsch = self.create_clebsch_cubic() | |
clebsch.set_color_by_gradient(RED, ORANGE) | |
clebsch.scale(1.5) | |
# Create the Steiner Surface approximation | |
steiner = self.create_steiner_surface() | |
steiner.set_color_by_gradient(GREEN, YELLOW) | |
steiner.scale(1.5) | |
# Create the Klein Bottle approximation | |
klein = self.create_klein_bottle() | |
klein.set_color_by_gradient(TEAL, PINK) | |
klein.scale(1.5) | |
# Transition between surfaces | |
self.add(kummer) | |
self.begin_ambient_camera_rotation(rate=0.1) | |
self.wait(2) | |
self.play(Transform(kummer, clebsch), run_time=3) | |
self.wait(2) | |
self.play(Transform(kummer, steiner), run_time=3) | |
self.wait(2) | |
self.play(Transform(kummer, klein), run_time=3) | |
self.wait(2) | |
self.play(FadeOut(kummer)) | |
self.wait() | |
def create_kummer_surface(self): | |
# Approximate Kummer Surface | |
surface = Surface( | |
lambda u, v: self.kummer_parametric(u, v), | |
u_range=[-PI, PI], | |
v_range=[-PI, PI], | |
resolution=(48, 48), | |
checkerboard_colors=None, | |
fill_opacity=1, | |
stroke_color=WHITE, | |
stroke_width=0.5, | |
) | |
return surface | |
def kummer_parametric(self, u, v): | |
# Parametric equations for Kummer surface approximation | |
a = 1 | |
x = a * np.cos(u) * np.cos(v) | |
y = a * np.sin(u) * np.cos(v) | |
z = a * np.sin(v) | |
return np.array([x, y, z]) | |
def create_clebsch_cubic(self): | |
# Approximate Clebsch Diagonal Cubic | |
surface = Surface( | |
lambda u, v: self.clebsch_parametric(u, v), | |
u_range=[0, PI], | |
v_range=[0, TAU], | |
resolution=(48, 48), | |
checkerboard_colors=None, | |
fill_opacity=1, | |
stroke_color=WHITE, | |
stroke_width=0.5, | |
) | |
return surface | |
def clebsch_parametric(self, u, v): | |
# Parametric equations for Clebsch diagonal cubic approximation | |
a = 1 | |
x = a * np.sin(u) * np.cos(v) | |
y = a * np.sin(u) * np.sin(v) | |
z = a * np.cos(u) | |
return np.array([x, y, z]) | |
def create_steiner_surface(self): | |
# Approximate Steiner Surface (Roman Surface) | |
surface = Surface( | |
lambda u, v: self.steiner_parametric(u, v), | |
u_range=[0, PI], | |
v_range=[0, PI], | |
resolution=(48, 48), | |
checkerboard_colors=None, | |
fill_opacity=1, | |
stroke_color=WHITE, | |
stroke_width=0.5, | |
) | |
return surface | |
def steiner_parametric(self, u, v): | |
# Parametric equations for Steiner surface approximation | |
a = 1 | |
x = a * np.sin(2 * u) * np.sin(v) | |
y = a * np.sin(2 * u) * np.cos(v) | |
z = a * np.cos(2 * u) | |
return np.array([x, y, z]) | |
def create_klein_bottle(self): | |
# Approximate Klein Bottle | |
surface = Surface( | |
lambda u, v: self.klein_parametric(u, v), | |
u_range=[0, TAU], | |
v_range=[0, TAU], | |
resolution=(48, 48), | |
checkerboard_colors=None, | |
fill_opacity=1, | |
stroke_color=WHITE, | |
stroke_width=0.5, | |
) | |
return surface | |
def klein_parametric(self, u, v): | |
# Parametric equations for Klein bottle approximation | |
r = 2 | |
x = (r + np.cos(u / 2) * np.sin(v) - np.sin(u / 2) * np.sin(2 * v)) * np.cos(u) | |
y = (r + np.cos(u / 2) * np.sin(v) - np.sin(u / 2) * np.sin(2 * v)) * np.sin(u) | |
z = np.sin(u / 2) * np.sin(v) + np.cos(u / 2) * np.sin(2 * v) | |
return np.array([x, y, z]) | |
from manim import * | |
import numpy as np | |
class MobiusInsideTorus(ThreeDScene): | |
def construct(self): | |
# Set up the initial camera orientation | |
self.set_camera_orientation(phi=75 * DEGREES, theta=45 * DEGREES) | |
# Create the Torus | |
torus = Surface( | |
lambda u, v: self.torus_func(u, v), | |
u_range=[0, TAU], | |
v_range=[0, TAU], | |
resolution=(100, 100), | |
fill_opacity=0.5, | |
stroke_color=WHITE, | |
stroke_width=0.5, | |
) | |
torus.set(color_by_rgb_func=self.hyperbolic_color_func) | |
# Create the Möbius Strip | |
mobius_strip = Surface( | |
lambda u, v: self.mobius_func(u, v), | |
u_range=[0, TAU], | |
v_range=[-1, 1], | |
resolution=(100, 30), | |
fill_opacity=1, | |
stroke_color=WHITE, | |
stroke_width=0.5, | |
) | |
mobius_strip.set(color_by_rgb_func=self.hyperbolic_color_func) | |
# Add surfaces to the scene | |
self.add(torus, mobius_strip) | |
self.wait(1) | |
# Animate camera rotation by updating theta | |
self.play( | |
Rotate( | |
self.camera.gamma_tracker, | |
angle=360 * DEGREES, | |
run_time=8, | |
rate_func=linear | |
) | |
) | |
self.wait(1) | |
def torus_func(self, u, v): | |
# Parametric equations for a torus | |
R = 3 # Major radius | |
r = 1 # Minor radius | |
x = (R + r * np.cos(v)) * np.cos(u) | |
y = (R + r * np.cos(v)) * np.sin(u) | |
z = r * np.sin(v) | |
return np.array([x, y, z]) | |
def mobius_func(self, u, v): | |
# Parametric equations for a Möbius strip adjusted to fit inside the torus | |
radius = 2 # Radius of the central circle | |
width = 0.6 # Width of the strip | |
twist = u / 2 # Half-twist | |
x = (radius + v * np.cos(twist)) * np.cos(u) | |
y = (radius + v * np.cos(twist)) * np.sin(u) | |
z = v * np.sin(twist) | |
return np.array([x, y, z]) | |
def hyperbolic_color_func(self, x, y, z): | |
# Color function to simulate hyperbolic colors | |
r = np.sqrt(x**2 + y**2 + z**2) | |
theta = np.arctan2(y, x) | |
phi = np.arccos(z / r) | |
hue = (theta + PI) / (2 * PI) | |
saturation = 0.8 | |
value = (np.sin(3 * phi) + 1) / 2 # Creates variation based on angle | |
return color.hsv_to_rgb(np.array([hue, saturation, value])) | |
from manim import * | |
import numpy as np | |
class PenroseTiling(Scene): | |
def construct(self): | |
# Generate Penrose tiling | |
tiling = self.create_penrose_tiling(order=5, scale=2) | |
self.add(tiling) | |
self.wait(2) | |
def create_penrose_tiling(self, order=5, scale=1): | |
# Initial large kite | |
tiles = self.deflate_tiles([self.initial_tile()], order) | |
group = VGroup() | |
for tile in tiles: | |
polygon = Polygon(*[scale * np.array(vertex) for vertex in tile['vertices']]) | |
polygon.set_fill(random_bright_color(), opacity=0.7) | |
polygon.set_stroke(WHITE, width=0.5) | |
group.add(polygon) | |
return group | |
def initial_tile(self): | |
# Defines the initial 'kite' tile | |
golden_ratio = (1 + np.sqrt(5)) / 2 | |
angle36 = PI / 5 | |
angle72 = 2 * PI / 5 | |
# Coordinates for the initial kite | |
A = [0, 0, 0] | |
B = [np.cos(0), np.sin(0), 0] | |
C = [np.cos(angle72), np.sin(angle72), 0] | |
D = [np.cos(-angle36), np.sin(-angle36), 0] | |
return { | |
'type': 'kite', | |
'vertices': [A, B, C, D] | |
} | |
def deflate_tiles(self, tiles, order): | |
if order == 0: | |
return tiles | |
new_tiles = [] | |
for tile in tiles: | |
new_tiles.extend(self.subdivide_tile(tile)) | |
return self.deflate_tiles(new_tiles, order - 1) | |
def subdivide_tile(self, tile): | |
# Subdivide tiles according to Penrose rules | |
golden_ratio = (1 + np.sqrt(5)) / 2 | |
if tile['type'] == 'kite': | |
A, B, C, D = tile['vertices'] | |
P = self.get_point(A, B, tau=golden_ratio) | |
new_tiles = [ | |
{'type': 'kite', 'vertices': [P, B, C, D]}, | |
{'type': 'dart', 'vertices': [A, P, D]} | |
] | |
elif tile['type'] == 'dart': | |
A, B, C = tile['vertices'] | |
P = self.get_point(B, A, tau=golden_ratio) | |
new_tiles = [ | |
{'type': 'kite', 'vertices': [P, B, C, A]}, # Added 'A' as the fourth vertex | |
{'type': 'dart', 'vertices': [A, P, C]} | |
] | |
else: | |
new_tiles = [] | |
return new_tiles | |
def get_point(self, point1, point2, tau): | |
# Calculates a point along the line between two points | |
return [ | |
point1[0] + (point2[0] - point1[0]) / tau, | |
point1[1] + (point2[1] - point1[1]) / tau, | |
0 | |
] | |
from manim import * | |
import numpy as np | |
class KnotToDuck(ThreeDScene): | |
def construct(self): | |
# Set up the camera | |
self.set_camera_orientation(phi=75 * DEGREES, theta=30 * DEGREES) | |
# Create the knot | |
knot = self.create_knot() | |
# Create the duck | |
duck = self.create_duck() | |
# Add the knot to the scene | |
self.add(knot) | |
self.wait(1) | |
# Morph the knot into the duck | |
self.play(Transform(knot, duck), run_time=5) | |
self.wait(2) | |
def create_knot(self): | |
# Define the parametric equations for the knot | |
knot = ParametricFunction( | |
self.knot_equation, | |
t_range=[0, TAU, TAU / 200], # Step size controls the number of points | |
color=BLUE_E, | |
) | |
knot.set_stroke(width=3) | |
return knot | |
def knot_equation(self, t): | |
# Simple trefoil knot equations | |
x = (2 + np.cos(3 * t)) * np.cos(2 * t) | |
y = (2 + np.cos(3 * t)) * np.sin(2 * t) | |
z = np.sin(3 * t) | |
return np.array([x, y, z]) / 3 # Scale down for better viewing | |
def create_duck(self): | |
# Approximate the duck shape using basic 3D shapes | |
body = Sphere(radius=1).shift(DOWN * 0.5) | |
head = Sphere(radius=0.5).shift(UP * 1.0 + OUT * 0.5) | |
beak = Cone(base_radius=0.2, height=0.3) | |
beak.rotate(PI / 2, axis=RIGHT).shift(UP * 1.0 + OUT * 0.9) | |
duck = VGroup(body, head, beak) | |
duck.set_color(YELLOW) | |
return duck | |
from manim import * | |
import numpy as np | |
class TorusToBiCylinder(ThreeDScene): | |
def construct(self): | |
# Set up the camera | |
self.set_camera_orientation(phi=75 * DEGREES, theta=30 * DEGREES) | |
# Create the Torus | |
torus = self.create_torus() | |
torus.set_color(BLUE_E) | |
torus.set_opacity(0.7) | |
# Create the Bi-Cylinder (intersection of two cylinders) | |
bicylinder = self.create_bicylinder() | |
bicylinder.set_color(RED_E) | |
bicylinder.set_opacity(0.7) | |
# Add the Torus to the scene | |
self.add(torus) | |
self.wait(1) | |
# Transform Torus into Bi-Cylinder | |
self.play(Transform(torus, bicylinder), run_time=5) | |
self.wait(2) | |
def create_torus(self): | |
# Define the torus as a ParametricSurface | |
torus = ParametricSurface( | |
self.torus_equation, | |
u_range=[0, TAU], | |
v_range=[0, TAU], | |
resolution=(48, 16), | |
checkerboard_colors=[BLUE_D, BLUE_E], | |
) | |
return torus | |
def torus_equation(self, u, v): | |
# Parametric equations for a torus | |
R = 2 # Major radius | |
r = 0.7 # Minor radius | |
x = (R + r * np.cos(v)) * np.cos(u) | |
y = (R + r * np.cos(v)) * np.sin(u) | |
z = r * np.sin(v) | |
return np.array([x, y, z]) | |
def create_bicylinder(self): | |
# Create two cylinders intersecting at right angles | |
cylinder1 = Cylinder(radius=2, height=4, direction=UP) | |
cylinder2 = Cylinder(radius=2, height=4, direction=RIGHT) | |
bicylinder = Intersection(cylinder1, cylinder2) | |
return bicylinder | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment