群友提出:
这个Poncelet闭合定理很有趣,给定一个椭圆(包含了圆,下同),以及自然数n,总能找到一个较小的椭圆(此处由 s_0 控制缩放因子),使得从大椭圆上任一点引切线到小椭圆上,再次交大椭圆于一点,不断重复这个过程,就能得到起点和重点重合,且刚好画出一个n边形。换句话说,这个n边形外接大椭圆,内切小椭圆。对于没有倾斜且焦点在x坐标轴上的椭圆,有较简单的公式,更一般的需要高等代数的知识来求解方程,且形式复杂,不便于展示。
只是不知道LaTeX有无现成的实现方式?
另附 mma 代码以供参考:
ClearAll["Global`*"];
a=2;b=3/2;n=6;
s0Exact=Cos[Pi/n];
s0Num=N[s0Exact];
eqOuter=x^2/a^2+y^2/b^2==1;
eqInnerParam=x^2/a^2+y^2/b^2==s^2;
Print["原外圆锥曲线方程: ",TraditionalForm[eqOuter]];
Print["带参数 s 的内圆锥曲线方程: ",TraditionalForm[eqInnerParam]];
Print["n = ",n];
Print["\ns0 = ",Style[s0Exact,Bold]," \[TildeTilde] ",Style[s0Num,Bold]];
tStart=Pi/3;
dt=2 Pi/n;
pts=Table[{a Cos[t],b Sin[t]},{t,tStart,tStart+n*dt,dt}];
contacts=Table[{s0Num a Cos[t+dt/2],s0Num b Sin[t+dt/2]},{t,tStart,tStart+(n-1)*dt,dt}];
mainColor=RGBColor["#9999FF"];
Show[ParametricPlot[{{a Cos[t],b Sin[t]},{s0Num a Cos[t],s0Num b Sin[t]}},{t,0,2 Pi},PlotStyle->{Directive[Black,Thick],Directive[Gray,Thick]}],Graphics[{Table[{mainColor,Thick,Arrowheads[0.035],Arrow[{pts[[i]],pts[[i+1]]}]},{i,1,n}],{Black,PointSize[0.012],Point[pts[[2;;-1]]]},{Darker[Gray],PointSize[0.008],Point[contacts]},{mainColor,PointSize[0.016],Point[pts[[1]]]}}],Axes->True,AspectRatio->Automatic,PlotRange->{{-a-0.4,a+0.4},{-b-0.4,b+0.4}},ImageSize->650,Background->White]
用同心圆做线性变换
%\usepackage{tikz}
%\usepackage{xfp}
\begin{tikzpicture}
\def\nsides{5}%多边形的边数
\def\outerradius{1}%外圆半径
\edef\innerradius{\fpeval{\outerradius*cosd(0.5*360/\nsides)}}%内圆半径
\def\angleoff{60}%画多边形时, 第一个点的角度
\def\xvsy{1.4}%x 轴的单位长度 对比 y 轴的单位长度的比例
\begin{scope}[rotate=30, xscale=\xvsy, ]
\draw circle [radius=\outerradius];
\draw circle [radius=\innerradius];
\draw (\angleoff:\outerradius) coordinate[label=\angleoff:$s_0$](s0)
\foreach[parse=true] \i in {1,2,...,\nsides-1}
{--(\angleoff+\i*360/\nsides:\outerradius)
coordinate[label=\angleoff+\i*360/\nsides:$s_{\i}$](s\i)}
-- cycle;
\end{scope}
\end{tikzpicture}
如果事先画出了两个椭圆, 可以用下面的计算交点的办法, 找出切线和切点
这里的难点在于「s0=cos(pi/n)」仅仅是一个特例,如何找到符合要求的小椭圆,是一个看上去复杂得多的数学问题。对于特例:
\documentclass{standalone}
\usepackage{luadraw}
\usepackage[svgnames]{xcolor}
\usepackage{fourier-otf}
\begin{document}
\begin{luadraw}{name=poncelet_ellipe}
local ld = luadraw
local cpx = ld.cpx
local g = ld.graph:new{window={-5,5,-4,4}}
local i, Zp, arg = cpx.I, cpx.Zp, cpx.arg
local sin, cos, pi = math.sin, math.cos, math.pi
local a, b, t = 4, 2.5, pi/3
local n = 5
local s0 = cos(pi/n)
local U = Zp(1,t)
local V = ld.rotate(U,360/n)
g:Savematrix()
g:Composematrix({0,a,b*i}) --
g:Dcircle({0,1},"thick");g:Dcircle({0,s0})
g:Dlabeldot("$P$",U,{pos="NE"})
for k = 1, n do
g:Dseg({U,V},1,"line cap=round,magenta,semithick")
g:Rotate(360/n)
end
g:Restorematrix()
g:Show()
\end{luadraw}
\end{document}
AFAIK,这都是比较简单的需求,考虑下面三个包:
texdoc tkz-euclide对于圆,有相关方法:texdoc tkz-elements对于椭圆,也有类似方法:texdoc luadraw同样的: