Skip to content

Instantly share code, notes, and snippets.

@rkevin-arch
Created May 3, 2018 10:36
Show Gist options
  • Save rkevin-arch/0091b10ac7573814ff9b452ac9b1bf54 to your computer and use it in GitHub Desktop.
Save rkevin-arch/0091b10ac7573814ff9b452ac9b1bf54 to your computer and use it in GitHub Desktop.
Quick demo of the Affine encryption process using the manim engine
#!/usr/bin/env python
from big_ol_pile_of_manim_imports import *
import math
import fractions
# Quick demo of the Affine encryption process, using c=3*p+7
# Of course, this entire animation relies on 3Blue1Brown's manim engine
# https://github.com/3b1b/manim
# A lot of code is copied from Solara570's projects
# https://github.com/Solara570/demo-solara
# Hastily hacked together by rkevin
# For demonstration purposes only.
# Usage: After getting manim running,
# python extract_scene.py AffineEncryptionTest.py AffineEncryption -p
class AffineEncryption(Scene):
CONFIG={
"radius":2.5,
"N":26,
"labelDist":0.4,
"circlePosition":ORIGIN,
"multtextSize":1.5,
"multfactor":3,
"addfactor":7
}
def construct(self):
self.circle=Arc(-2*np.pi,color=WHITE, start_angle=np.pi/2, radius=self.radius)
self.circle.shift(self.circlePosition)
self.play(ShowCreation(self.circle))
self.dots=self.getDots()
self.labels=self.getLabelNames()
self.updateLabelPositions(self.dots,self.labels)
self.play(DrawBorderThenFill(self.dots),Write(self.labels))
plaintextold=self.getLabelNames()
plaintextnew=self.getLabelNames()
self.updateLabelPositions(self.dots,plaintextold)
self.updateLabelPositions(self.dots,plaintextnew,1)
self.play(Transform(plaintextold,plaintextnew))
self.multtext=TexMobject("p").scale(self.multtextSize).shift(self.circlePosition)
self.play(Write(self.multtext))
self.wait()
multfactor=self.multfactor
dots2=self.getDots(multfactor)
labels2=self.getLabelNames()
self.updateLabelPositions(dots2,labels2)
multtext2=TexMobject("c=p\\times%d"%multfactor).scale(self.multtextSize).shift(self.circlePosition)
self.play(Transform(self.multtext,multtext2))
self.play(*([MoveAlongPath(self.dots[i],ParametricFunction(
lambda t:
[self.radius*np.cos(t*-2*np.pi/self.N+np.pi/2),
self.radius*np.sin(t*-2*np.pi/self.N+np.pi/2),
0]
,t_min=i
,t_max=i*multfactor
),run_time=5) for i in range(self.N)]+
[MoveAlongPath(self.labels[i],ParametricFunction(
lambda t:
[(self.radius+0.4)*np.cos(t*-2*np.pi/self.N+np.pi/2),
(self.radius+0.4)*np.sin(t*-2*np.pi/self.N+np.pi/2),
0]
,t_min=i
,t_max=i*multfactor
),run_time=5) for i in range(self.N)]))
self.wait()
addfactor=self.addfactor
dots2=self.getDots(multfactor,addfactor)
self.updateLabelPositions(dots2,labels2)
multtext2=TexMobject("c=p\\times%d+%d"%(multfactor,addfactor)).scale(self.multtextSize).shift(self.circlePosition)
self.play(Transform(self.multtext,multtext2))
self.play(*([MoveAlongPath(self.dots[i],ParametricFunction(
lambda t:
[self.radius*np.cos(t*-2*np.pi/self.N+np.pi/2),
self.radius*np.sin(t*-2*np.pi/self.N+np.pi/2),
0]
,t_min=i*multfactor
,t_max=i*multfactor+addfactor
),run_time=2) for i in range(self.N)]+
[MoveAlongPath(self.labels[i],ParametricFunction(
lambda t:
[(self.radius+0.4)*np.cos(t*-2*np.pi/self.N+np.pi/2),
(self.radius+0.4)*np.sin(t*-2*np.pi/self.N+np.pi/2),
0]
,t_min=i*multfactor
,t_max=i*multfactor+addfactor
),run_time=2) for i in range(self.N)]))
self.wait()
def getDots(self,multfactor=1,addfactor=0):
return VGroup(*[
Dot(color=WHITE).move_to(vertex)
for vertex in self.getVertices(multfactor,addfactor)
])
def getVertices(self,multfactor=1,addfactor=0):
angle = -2 * np.pi / self.N
return np.array([
rotate_vector(UP*self.radius,(k+addfactor)*angle*multfactor)+self.circlePosition
for k in range(self.N)
])
#polygon=RegularPolygon(n=self.N, start_angle=np.pi/2)
#polygon.scale(self.radius)
#polygon.move_to(circle,aligned_edge=UP)
#return polygon.get_vertices()[:-1]
def getLabelNames(self):
return VGroup(*[
TexMobject("%c"%chr(ord('A')+i))
for i in range(self.N)
])
def updateLabelPositions(self, dots, labels, dist=0.4):
def updateLabelsFunc(self):
for dot,label in zip(dots, labels):
label.move_to(dot)
vect=dot.get_center()-self.get_center()
vect/=np.linalg.norm(vect)
label.shift(dist*vect) # 0.4 subject to change
return labels
UpdateFromFunc(labels,updateLabelsFunc).update(0)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment