100 如何基于 TikZ/luadraw/Asy 复刻Poncelet闭合定理?

发布于 2026-11-08 17:08:53

群友提出:

这个Poncelet闭合定理很有趣,给定一个椭圆(包含了圆,下同),以及自然数n,总能找到一个较小的椭圆(此处由 s_0 控制缩放因子),使得从大椭圆上任一点引切线到小椭圆上,再次交大椭圆于一点,不断重复这个过程,就能得到起点和重点重合,且刚好画出一个n边形。换句话说,这个n边形外接大椭圆,内切小椭圆。对于没有倾斜且焦点在x坐标轴上的椭圆,有较简单的公式,更一般的需要高等代数的知识来求解方程,且形式复杂,不便于展示。
image.png
只是不知道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]

查看更多

关注者
1
被浏览
160
越来越少
越来越少 3天前
这家伙很懒,什么也没写!

用同心圆做线性变换

%\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}

6b41b64a680c2b67f21c73c48eb28594.png

如果事先画出了两个椭圆, 可以用下面的计算交点的办法, 找出切线和切点
7df52951bd46c011fb6fa3b1f32c54d2.png

3 个回答
Sagittarius Rover
这家伙很懒,什么也没写!

这里的难点在于「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}

image.png

茶凉凉凉凉丶
这家伙很懒,什么也没写!

我是提出问题的人,补充一下,这里$s_0=\cos(\pi/n)$,对于图上这种很端正的情况,大小椭圆都是容易绘制的,关键是如何正确绘制出切线呢?
以及,如果内椭圆有倾斜、平移,就没有如此简单的公式了,只能进行数值求解。

撰写答案

请登录后再发布答案,点击登录

发布
问题

分享
好友

手机
浏览

扫码手机浏览