Last active
October 7, 2022 13:32
-
-
Save folex/adcb44b01f863f6f272f5fbd3d0ff505 to your computer and use it in GitHub Desktop.
Fluence Network Animation written in Manim
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 math import sqrt | |
import random | |
import networkx as nx | |
nxgraph = nx.erdos_renyi_graph(11, 0.003) | |
# nxgraph = nx.gnp_random_graph(50, 0.2) | |
# nxgraph = nx.barabasi_albert_graph(50, 1) | |
# nxgraph = nx.random_lobster(150, 0.1, 0.1) | |
def line(a, b): | |
return Line(a.get_center(), b.get_center()) | |
def rnd_delay(ans): | |
def pause(m): | |
a = Animation(Mobject(),run_time=random.random()) | |
return a | |
return [AnimationGroup(*[pause(i), a.set_run_time(random.random() + 0.5)], lag_ratio=1) for (i, a) in enumerate(ans)] | |
# def distance(a, b): | |
# # ac = a.get_center() | |
# # bc = b.get_center() | |
# diff = a.get_center() - b.get_center() | |
# return sqrt(diff[0]**2 + diff[1]**2) | |
def Edge(u, v, z_index=None): | |
return DashedLine(u, v, dash_length=random.uniform(0.03, 0.07), z_index=z_index, stroke_opacity=0.9, stroke_width=0.5) | |
class ParticleDemo(MovingCameraScene): | |
def show_line(self, a, b, text): | |
l = line(a, b) | |
anis = [Create(l)] | |
if text is not None: | |
anis.append(Write(Text(text, font_size=32).next_to(l.get_center(), DOWN).rotate(l.get_angle()))) | |
return (AnimationGroup(*anis), l) | |
def dashed_line(self, a, b): | |
l = DashedLine(a.get_center(), b.get_center()) | |
self.play(Create(l)) | |
return l | |
def construct(self): | |
self.camera.frame.save_state() | |
G = Graph.from_networkx(nxgraph, layout="shell", edge_type=Edge) | |
# G = Graph.from_networkx(nx.cycle_graph(17), layout="circular") | |
client = Dot([-5, -3, 0]) | |
self.play(Create(G), Create(Text("p2p network").next_to(G, UP, buff=0.5))) | |
self.play( | |
Create(client), | |
Create(Text("client", font_size = 32).next_to(client, LEFT)), | |
self.camera.frame.animate.scale(0.7).move_to(client) | |
) | |
# self.play(client.animate.add_line_to(G[10].get_center())) | |
# self.play(client.animate.add_smooth_curve_to(G[10].get_center())) | |
l1_ani, l1 = self.show_line(client, G[10], "connects to") | |
self.play(l1_ani, self.camera.frame.animate.move_to(l1.get_center())) | |
self.play(self.camera.frame.animate.move_to(G[10].get_center())) | |
self.play( | |
# AnimationGroup(*[l1_ani, self.camera.frame.animate.move_to(l1.get_center())]), | |
# self.camera.frame.animate.scale(1), | |
Create(Circle().set_color(RED_C).surround(G[10])), | |
Write(Text("relay", font_size = 32).next_to(G[10], LEFT)) | |
) | |
p = LabeledDot("particle").set_color(ORANGE) | |
p.move_to(client) | |
def track_particle(frame): | |
frame.move_to(p.get_center()) | |
self.play(Create(p), p.animate.scale(2), self.camera.frame.animate.move_to(p.get_center())) | |
self.camera.frame.add_updater(track_particle, call_updater = False) | |
self.add_foreground_mobject(p) | |
self.play(MoveAlongPath(p, l1), rate_func=linear) | |
# for (i, v) in enumerate(G.vertices): | |
# print("v", v) | |
lines = [Line(G[10].get_center(), G[v].get_center(), stroke_width=0.6) for (i, v) in enumerate(G.vertices) if random.choice([True, False])] | |
if len(lines) > 0: | |
self.play(*[Create(l) for l in lines]) | |
ps = [p] + [p.copy() for _ in range(len(lines))] | |
# self.play(*[p.animate.shift(LEFT*i*0.1) for (i, p) in enumerate(ps)]) | |
anis = [MoveAlongPath(ps[i], lines[i]) for i in range(len(lines))] | |
forward = rnd_delay(anis) | |
self.play(*forward) | |
# TODO: display something on every particle merge | |
anis = [MoveAlongPath(ps[i], lines[i].reverse_direction()) for i in range(len(lines))] | |
backward = rnd_delay(anis) | |
self.play(*forward) | |
self.remove(*ps) | |
self.add(p) | |
self.play(p.animate.move_to(client)) | |
# self.bring_to_front(p) | |
# l2 = self.show_line(G[10], G[0]) | |
# self.play(p.animate.move_to(G[0])) | |
# line = line.append_points(Line(p2,p3).points).append_points(Line(p3,p4).points) | |
# self.play(line.animate.put_start_and_end_on(client.get_center(), G[0].get_center())) | |
# self.play(line.animate.append_points(Line(G[10].get_center(), G[0].get_center()).points)) | |
# self.play(*[G[v].animate.move_to(ind) | |
# for ind, v in enumerate(G.vertices)]) | |
# self.play(Uncreate(G)) | |
# G.vertices | |
# {v: vertex_type(**self._vertex_config[v]) for v in vertices} | |
# self.play(G.animate.add_vertices(*{"gg": (0, 0)})) | |
# self.play(G.animate.add_vertices(*["d", "e", "f"])) | |
self.wait(0.5) | |
self.camera.frame.remove_updater(track_particle) | |
self.play(self.camera.frame.animate.restore()) | |
self.wait(3) | |
# 5*RIGHT*np.cos(ind/7 * PI) + 3*UP*np.sin(ind/7 * PI) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment