Skip to content

Instantly share code, notes, and snippets.

@uwezi
Last active October 24, 2024 18:15
Show Gist options
  • Save uwezi/70d58d26e0171b64c6dfc4108b61b476 to your computer and use it in GitHub Desktop.
Save uwezi/70d58d26e0171b64c6dfc4108b61b476 to your computer and use it in GitHub Desktop.
[Heptadecagon] Geometric construction of a heptadecagon. #manim #animation #geometry #circle #intersection #line #compass
from manim import *
# https://discord.com/channels/581738731934056449/1298699478194196612/1298699478194196612
class heptadecagon(MovingCameraScene):
def construct(self):
# after https://www.youtube.com/watch?v=xGUWVPOks00 AleeDrawing
self.add(NumberPlane().add_coordinates())
def circle_line_intersection(circle, line):
# source https://mathworld.wolfram.com/Circle-LineIntersection.html
cline = line.copy().shift(-circle.get_arc_center())
x0,y0 = circle.get_arc_center()[0:2]
x1,y1 = cline.get_start()[0:2]
x2,y2 = cline.get_end()[0:2]
r = circle.width/2
dx = x2-x1
dy = y2-y1
dr = np.sqrt(dx**2+dy**2)
D = x1*y2 - x2*y1
Delta = r**2*dr**2-D**2
print(f"\nx1={x1:.3f} y1={y1:.3f} x2={x2:.3f} y2={y2:.3f} x0={x0:.3f} y0={y0:.3f}\n")
print(f"\ndx={dx:.3f} dy={dy:.3f} dr={dr:.3f} D={D:.3f} Δ={Delta:.3f}\n")
if Delta < 0:
return []
sx1 = (D*dy+np.sign(dy)*dx*np.sqrt(Delta))/(dr**2)+x0
sx2 = (D*dy-np.sign(dy)*dx*np.sqrt(Delta))/(dr**2)+x0
sy1 = (-D*dx+np.abs(dy)*np.sqrt(Delta))/(dr**2)+y0
sy2 = (-D*dx-np.abs(dy)*np.sqrt(Delta))/(dr**2)+y0
if Delta==0:
return [np.array([sx1,sy1,0])]
else:
return [
np.array([sx1,sy1,0]),
np.array([sx2,sy2,0])
]
def circle_circle_intersection(circ1, circ2):
# source https://www.johndcook.com/blog/2023/08/27/intersect-circles/
c0 = circ1.get_center()
c1 = circ2.get_center()
r0 = circ1.width/2
r1 = circ2.width/2
v = c1 - c0
d = np.linalg.norm(v)
if d > r0 + r1 or d == 0:
return []
u = v/np.linalg.norm(v)
xvec = c0 + (d**2 - r1**2 + r0**2)*u/(2*d)
uperp = np.array([u[1], -u[0], 0])
a = ((-d+r1-r0)*(-d-r1+r0)*(-d+r1+r0)*(d+r1+r0))**0.5/d
return [xvec + a*uperp/2, xvec - a*uperp/2]
def line_line_intersection(line1, line2):
return line_intersection([line1.get_start(),line1.get_end()],[line2.get_start(),line2.get_end()])
A = ORIGIN
r = 3
Adot = VGroup(Dot(point=A), MathTex(r"A").next_to(A,DOWN))
circ = Circle(radius=r, arc_center=A)
self.add(Adot)
self.play(Create(circ))
BC = Line(1.2*r*LEFT,1.2*r*RIGHT).rotate(40*DEGREES).shift(A)
self.play(Create(BC))
B,C = circle_line_intersection(circ,BC)
Bdot = VGroup(Dot(point=B), MathTex(r"B").next_to(B,UP))
Cdot = VGroup(Dot(point=C), MathTex(r"C").next_to(C,DOWN))
self.play(Create(Bdot),Create(Cdot))
circ2 = Circle(radius=r, arc_center=B, color=BLUE, stroke_width=1)
self.play(Create(circ2))
self.play(BC.animate.scale(1.6, about_point=C))
D1,D2 = circle_line_intersection(circ2,BC)
Ddot = VGroup(Dot(point=D1), MathTex(r"D").next_to(D1,RIGHT))
self.play(Create(Ddot))
circ3 = Circle(radius=2*r, color=BLUE, stroke_width=1, arc_center=D1)
self.play(Create(circ3))
F,E = circle_circle_intersection(circ,circ3)
Edot = VGroup(Dot(point=E), MathTex(r"E").next_to(E,UL))
Fdot = VGroup(Dot(point=F), MathTex(r"F").next_to(F,UP))
self.play(Create(Edot),Create(Fdot))
EF = Line(E,F, stroke_width=1, color=BLUE)
self.play(Create(EF))
G1,G2 = circle_line_intersection(circ2, EF)
H = line_line_intersection(EF,BC)
Gdot = VGroup(Dot(point=G1), MathTex(r"G").next_to(G1,UR))
Hdot = VGroup(Dot(point=H), MathTex(r"H").next_to(H,UP))
self.play(Create(Gdot))
self.play(Create(Hdot))
r4 = np.linalg.norm(G1-C)
circ4 = Circle(radius=r4, color=BLUE, stroke_width=1, arc_center=C)
self.play(Create(circ4))
I, J = circle_circle_intersection(circ, circ4)
Idot = VGroup(Dot(point=I), MathTex(r"I").next_to(I,UP))
Jdot = VGroup(Dot(point=J), MathTex(r"J").next_to(J,UP))
self.play(Create(Idot),Create(Jdot))
IJ = Line(I,J, stroke_width=1,color=BLUE)
self.play(Create(IJ))
r5 = np.linalg.norm(H-J)
circ5 = Circle(radius=r5,arc_center=H, stroke_width=1,color=BLUE)
self.play(Create(circ5))
K1,K = circle_line_intersection(circ5,BC)
Kdot = VGroup(Dot(point=K), MathTex(r"K").next_to(K,UP))
self.play(Create(Kdot))
circ6 = Circle(radius=r5, arc_center=K, stroke_width=1, color=BLUE)
circ7 = Circle(radius=r5, arc_center=J, stroke_width=1, color=BLUE)
self.play(Create(circ6))
self.play(Create(circ7),self.camera.frame.animate.scale(1.4))
L,L2 = circle_circle_intersection(circ6, circ7)
Ldot = VGroup(Dot(point=L), MathTex(r"L").next_to(L,UP))
self.play(Create(Ldot))
LH = Line(L,H,stroke_width=1,color=BLUE)
self.play(Create(LH))
M1,M = circle_line_intersection(circ5,LH)
Mdot = VGroup(Dot(point=M), MathTex(r"M").next_to(M,UP))
self.play(Create(Mdot))
circ8 = Circle(radius=r5, arc_center=M, stroke_width=1, color=BLUE)
self.play(Create(circ8))
N1,N = circle_circle_intersection(circ8, circ6)
Ndot = VGroup(Dot(point=N), MathTex(r"N").next_to(N,UP))
self.play(Create(Ndot))
NH = Line(N,H, stroke_width=1,color=BLUE)
self.play(Create(NH))
O = line_line_intersection(NH, IJ)
Odot = VGroup(Dot(point=O), MathTex(r"O").next_to(O,DOWN))
r9 = np.linalg.norm(J-B)
circ9 = Circle(radius=r9, arc_center=H, stroke_width=1,color=BLUE)
self.play(Create(circ9))
P = circle_line_intersection(circ9, NH)[1]
Pdot = VGroup(Dot(point=P), MathTex(r"P").next_to(P,LEFT))
self.play(Create(Pdot))
circ10 = Circle(radius=r, arc_center=P, stroke_width=1, color=BLUE)
self.play(Create(circ10))
circ11 = Circle(radius=r, arc_center=H, stroke_width=1,color=BLUE)
self.play(Create(circ11))
Q = circle_circle_intersection(circ10, circ11)[1]
Qdot = VGroup(Dot(point=Q), MathTex(r"Q").next_to(Q,RIGHT))
X = circle_circle_intersection(circ,circ11)[1]
Xdot = VGroup(Dot(point=X), MathTex(r"X").next_to(X,DR))
self.play(Create(Qdot))
self.play(Create(Xdot))
QH = Line(Q,H,stroke_width=1,color=BLUE)
self.play(Create(QH))
R = line_line_intersection(QH,IJ)
Rdot = VGroup(Dot(point=R), MathTex(r"R").next_to(R,UR))
self.play(Create(Rdot))
circ12 = Circle(radius=r5, arc_center=R,stroke_width=1,color=BLUE)
self.play(Create(circ12))
T,S = circle_circle_intersection(circ12,circ7)
TS = Line(T,S,stroke_width=1,color=BLUE)
self.play(Create(TS))
U = line_line_intersection(TS,IJ)
Udot = VGroup(Dot(point=U), MathTex(r"U").next_to(U,LEFT))
self.play(Create(Udot))
r13 = np.linalg.norm(U-R)
circ13 = Circle(radius=r13, arc_center=U, stroke_width=1,color=BLUE)
self.play(Create(circ13))
V = circle_line_intersection(circ13,BC)[0]
Vdot = VGroup(Dot(point=V), MathTex(r"V").next_to(V,UP))
self.play(Create(Vdot))
r14 = np.linalg.norm(O-V)
circ14 = Circle(radius=r14, arc_center=O, stroke_width=1,color=BLUE)
self.play(Create(circ14))
W = circle_line_intersection(circ14,IJ)[0]
Wdot = VGroup(Dot(point=W), MathTex(r"W").next_to(W,LEFT))
self.play(Create(Wdot))
r15 = np.linalg.norm(W-X)
circ15 = Circle(radius=r15, arc_center=X, stroke_width=1,color=BLUE)
self.play(Create(circ15))
Y = circle_line_intersection(circ15,EF)[1]
Ydot = VGroup(Dot(point=Y), MathTex(r"Y").next_to(Y,UR))
self.play(Create(Ydot))
WY = Line(Y,W,stroke_width=1,color=BLUE)
self.play(Create(WY))
self.play(WY.animate.scale(2*r/WY.get_length(),about_point=W))
Z,P9 = circle_line_intersection(circ,WY)
Zdot = VGroup(Dot(point=Z), MathTex(r"Z").next_to(Z,UR))
self.play(Create(Zdot))
r16 = np.linalg.norm(J-Z)
circ16 = Circle(radius=r16,arc_center=Z,stroke_width=1,color=BLUE)
self.play(Create(circ16))
P7 = circle_circle_intersection(circ,circ16)[1]
P7dot = VGroup(Dot(point=P7), MathTex(r"P_7").next_to(P7,LEFT)).set_color(RED)
self.play(Create(P7dot))
circ16b = Circle(radius=r16,arc_center=P7,stroke_width=1,color=BLUE)
P12 = circle_circle_intersection(circ,circ16b)[1]
P12dot = VGroup(Dot(point=P12), MathTex(r"P_{12}").next_to(P12,DR)).set_color(RED)
self.play(Create(P12dot))
circ16c = Circle(radius=r16,arc_center=P12,stroke_width=1,color=BLUE)
self.play(Create(circ16c))
P17 = circle_circle_intersection(circ,circ16c)[1]
P17dot = VGroup(Dot(point=P17), MathTex(r"P_{17}").next_to(P17,DR)).set_color(RED)
self.play(Create(P17dot))
circ16d = Circle(radius=r16,arc_center=P17,stroke_width=1,color=BLUE)
self.play(Create(circ16d))
P5 = circle_circle_intersection(circ,circ16d)[1]
P5dot = VGroup(Dot(point=P5), MathTex(r"P_{5}").next_to(P5,UP)).set_color(RED)
self.play(Create(P5dot))
circ16e = Circle(radius=r16,arc_center=P5,stroke_width=1,color=BLUE)
self.play(Create(circ16e))
P10 = circle_circle_intersection(circ,circ16e)[1]
P10dot = VGroup(Dot(point=P10), MathTex(r"P_{10}").next_to(P10,DL)).set_color(RED)
self.play(Create(P10dot))
circ16f = Circle(radius=r16,arc_center=P10,stroke_width=1,color=BLUE)
self.play(Create(circ16f))
P15 = circle_circle_intersection(circ,circ16f)[1]
P15dot = VGroup(Dot(point=P15), MathTex(r"P_{15}").next_to(P15,DR)).set_color(RED)
self.play(Create(P15dot))
r17 = np.linalg.norm(J-P15)
circ17 = Circle(radius=r17,arc_center=P12,stroke_width=1,color=BLUE)
self.play(Create(circ17))
P11,P13 = circle_circle_intersection(circ,circ17)
P11dot = VGroup(Dot(point=P11), MathTex(r"P_{11}").next_to(P11,DOWN)).set_color(RED)
P13dot = VGroup(Dot(point=P13), MathTex(r"P_{13}").next_to(P13,DR)).set_color(RED)
self.play(Create(P11dot))
self.play(Create(P13dot))
P14dot = VGroup(Dot(point=J), MathTex(r"P_{14}").next_to(J,DR)).set_color(RED)
self.play(Create(P14dot))
circ17b = Circle(radius=r17,arc_center=P17,stroke_width=1,color=BLUE)
self.play(Create(circ17b))
P16,P1 = circle_circle_intersection(circ,circ17b)
P1dot = VGroup(Dot(point=P1), MathTex(r"P_{1}").next_to(P1,UR)).set_color(RED)
P16dot = VGroup(Dot(point=P16), MathTex(r"P_{16}").next_to(P16,RIGHT)).set_color(RED)
self.play(Create(P1dot))
self.play(Create(P16dot))
P2 = Z
P2dot = VGroup(Dot(point=Z), MathTex(r"P_{2}").next_to(Z,UR)).set_color(RED)
self.play(Create(P2dot))
circ17c = Circle(radius=r17,arc_center=P2,stroke_width=1,color=BLUE)
self.play(Create(circ17c))
P3 = circle_circle_intersection(circ,circ17c)[1]
P3dot = VGroup(Dot(point=P3), MathTex(r"P_{3}").next_to(P3,UP)).set_color(RED)
self.play(Create(P3dot))
circ17d = Circle(radius=r17,arc_center=P5,stroke_width=1,color=BLUE)
self.play(Create(circ17d))
P4,P6 = circle_circle_intersection(circ,circ17d)
P4dot = VGroup(Dot(point=P4), MathTex(r"P_{4}").next_to(P4,UP)).set_color(RED)
P6dot = VGroup(Dot(point=P6), MathTex(r"P_{6}").next_to(P6,UL)).set_color(RED)
self.play(Create(P4dot))
self.play(Create(P6dot))
P9dot = VGroup(Dot(point=P9), MathTex(r"P_{9}").next_to(P9,LEFT)).set_color(RED)
self.play(Create(P9dot))
circ17e = Circle(radius=r17,arc_center=P9,stroke_width=1,color=BLUE)
self.play(Create(circ17e))
P8 = circle_circle_intersection(circ,circ17e)[0]
P8dot = VGroup(Dot(point=P8), MathTex(r"P_{8}").next_to(P8,LEFT)).set_color(RED)
self.play(Create(P8dot))
#self.add(*[MathTex(f"{i}",color=RED).move_to(p) for i,p in enumerate(P15)])
#self.add(*[MathTex(f"{i}",color=GREEN).move_to(p) for i,p in enumerate(X)])
self.wait(2)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment