after a discussion on https://discord.com/channels/581738731934056449/1298699478194196612/1298699478194196612
inspired by https://www.youtube.com/watch?v=xGUWVPOks00 AleeDrawing
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) | |
after a discussion on https://discord.com/channels/581738731934056449/1298699478194196612/1298699478194196612
inspired by https://www.youtube.com/watch?v=xGUWVPOks00 AleeDrawing