椭圆的准圆

MATLAB | 三个趣的圆相关的数理性质可视化-LMLPHP

命题1: 椭圆外一点向椭圆做两条切线,若两切线垂直,则点的轨迹为圆形。

简单说明下为啥:
对于椭圆 x 2 a 2 + y 2 b 2 = 1 \frac{x^2}{a^2}+\frac{y^2}{b^2}=1 a2x2+b2y2=1,假设其过 ( m , n ) (m,n) (m,n)点的切线方程为 y − n = k ( x − m ) y-n=k(x-m) yn=k(xm),带入得椭圆方程得:

b 2 x 2 + a 2 ( k 2 ( x − m ) 2 + 2 n k ( x − m ) + n 2 ) − x 2 b 2 = 0 ( a 2 k 2 + b 2 ) x 2 + 2 k a 2 ( n − m k ) x + a 2 ( k m − n ) 2 − a 2 b 2 = 0 \begin{aligned} &b^2x^2+a^2(k^2(x-m)^2+2nk(x-m)+n^2)-x^2b^2=0\\ &(a^2k^2+b^2)x^2+2ka^2(n-mk)x+a^2(km-n)^2-a^2b^2=0 \end{aligned} b2x2+a2(k2(xm)2+2nk(xm)+n2)x2b2=0(a2k2+b2)x2+2ka2(nmk)x+a2(kmn)2a2b2=0

由于求的是切线因而 Δ = 0 \Delta=0 Δ=0,即 ( m 2 − a 2 ) k 2 − 2 m n k + n 2 − b 2 (m^2-a^2)k^2-2mnk+n^2-b^2 (m2a2)k22mnk+n2b2,这是一个关于 k k k的约束条件,由伟达定理得到两条切线的斜率 k 1 , k 2 k_1,k_2 k1,k2满足条件:
k 1 k 2 = n 2 − b 2 m 2 − a 2 k_1k_2=\frac{n^2-b^2}{m^2-a^2} k1k2=m2a2n2b2
由于两切线垂直,因此 k 1 k 2 = − 1 k_1k_2=-1 k1k2=1,因而有:
m 2 + n 2 = a 2 + b 2 m^2+n^2=a^2+b^2 m2+n2=a2+b2
是一个半径为 a 2 + b 2 \sqrt{a^2+b^2} a2+b2 的圆。

可视化效果:
MATLAB | 三个趣的圆相关的数理性质可视化-LMLPHP

MATLAB代码:

function directorC
% @author : slandarer
% 公众号  : slandarer随笔
% 知乎    : hikari
a=3;b=2;syms k
% axes基础属性设置
ax=gca;
hold on;grid on
ax.XLim=[-6,6];
ax.YLim=[-4,4];
ax.DataAspectRatio=[1,1,1];
ax.XAxisLocation='origin';
ax.YAxisLocation='origin';
ax.LineWidth=1.5;
ax.XMinorTick='on';
ax.YMinorTick='on';
ax.GridLineStyle='-.';
ax.GridAlpha=.09;
% 绘制圆和椭圆
t=linspace(0,2*pi,200);
plot(a.*cos(t),b.*sin(t),'LineWidth',2.5,'Color',[0,118,168]./255)
plot(sqrt(a^2+b^2).*cos(t),sqrt(a^2+b^2).*sin(t),'LineWidth',2.5,'Color',[169,64,71]./255)
% 绘制切线和交点
thetaList=linspace(0,2*pi,200);
kline1=plot(0,0,'-.','LineWidth',1.5,'Color',[1,1,1].*.5);
kline2=plot(0,0,'-.','LineWidth',1.5,'Color',[1,1,1].*.5);
kpnt=scatter(a,0,'filled','CData',[1,1,1].*.3);
X=-6:.1:6;
% 循环绘图
for i=1:length(thetaList)
    theta=thetaList(i);
    m=sqrt(a^2+b^2).*cos(theta);
    n=sqrt(a^2+b^2).*sin(theta);
    kk=double(solve((m^2-a^2)*k^2-2*m*n*k+n^2-b^2==0));
    Y1=kk(1).*(X-m)+n;Y2=kk(2).*(X-m)+n;
    kline1.XData=X;kline1.YData=Y1;
    kline2.XData=X;kline2.YData=Y2;
    kpnt.XData=m;
    kpnt.YData=n;
    drawnow;
    pause(.01)
end
end

旋转的错觉

命题2: 假设有半径为 r 2 \frac{r}{2} 2r的小圆在半径为 r r r大圆内滚动,小圆上的点轨迹为直线。

证明很简单,假设此时小圆上有一点与大圆接触,且此时小圆圆心与原点的连线与x轴正方向的夹角为 θ 0 \theta_0 θ0,现假设小圆滚动导致小圆圆心夹角变化 θ \theta θ,由于小圆半径为大圆的一半,因而当滚过相同路程时,小圆上的点的夹角反方向变化 2 θ 2\theta 2θ因而可以求出该小圆上点位置变化参数方程:

{ x = r 2 c o s ( θ 0 + θ ) + r 2 c o s ( θ 0 + θ − 2 θ ) y = r 2 s i n ( θ 0 + θ ) + r 2 s i n ( θ 0 + θ − 2 θ ) ⇒ { x = ( r 2 c o s ( θ ) ) c o s ( θ 0 ) y = ( r 2 c o s ( θ ) ) s i n ( θ 0 ) \begin{aligned} &\left\{\begin{matrix} x=\frac{r}{2}cos(\theta_0+\theta)+\frac{r}{2}cos(\theta_0+\theta-2\theta)\\ y=\frac{r}{2}sin(\theta_0+\theta)+\frac{r}{2}sin(\theta_0+\theta-2\theta)\\ \end{matrix}\right. \\ \Rightarrow &\left\{\begin{matrix} x=(\frac{r}{2}cos(\theta))cos(\theta_0)\\ y=(\frac{r}{2}cos(\theta))sin(\theta_0) \end{matrix}\right. \end{aligned} {x=2rcos(θ0+θ)+2rcos(θ0+θ2θ)y=2rsin(θ0+θ)+2rsin(θ0+θ2θ){x=(2rcos(θ))cos(θ0)y=(2rcos(θ))sin(θ0)

这不就是一个过原点,角度为 θ 0 \theta_0 θ0的直线嘛,证明完毕,小圆上所有点都走直线,为了可视化看起来好看,这里画几个等分的点搞一些可视化:

可视化效果:
MATLAB | 三个趣的圆相关的数理性质可视化-LMLPHP
MATLAB | 三个趣的圆相关的数理性质可视化-LMLPHP

MATLAB代码:

function PointOnLineInCircle(N)
% @author : slandarer
% 公众号  : slandarer随笔
% 知乎    : hikari
if nargin<1||N<2
    N=4;
end
% 0.2157    0.3765    0.5725
% 0.3098    0.5059    0.7412

% figure及axes基础属性设置
fig=gcf;
fig.Name='PoLiC';
fig.Position=[50 100 600 600];
fig.NumberTitle='off';
fig.MenuBar='none';
%
ax=axes(fig);
ax.Position=[0 0 1 1];
ax.XLim=[-2.05 2.05];
ax.YLim=[-2.05 2.05];
ax.XColor='none';
ax.YColor='none';
hold(ax,'on');
% grid on

thetaB=0;
thetaS=0;


% 绘制直线
pntsTheta=0:2*pi/N:2*pi;
for i=1:(length(pntsTheta)-1)
    plot([cos(pntsTheta(i)),cos(pntsTheta(i)+pi)].*2,...
         [sin(pntsTheta(i)),sin(pntsTheta(i)+pi)].*2,...
         'Color',[0.8 0.8 0.8],'LineWidth',1.5)
end
if mod(N,2)==0
    for i=1:(length(pntsTheta)-1)
        plot([cos(pntsTheta(i)+2*pi/N/2),cos(pntsTheta(i)+2*pi/N/2+pi)].*2,...
             [sin(pntsTheta(i)+2*pi/N/2),sin(pntsTheta(i)+2*pi/N/2+pi)].*2,...
             'Color',[0.8 0.8 0.8],'LineWidth',1.5)
    end
end
% 绘制大圆
tempT=0:0.1:2*pi+0.1;
CPnts=[cos(tempT);sin(tempT)];
plot(CPnts(1,:).*2,CPnts(2,:).*2,'Color',[0.2098 0.4059 0.6412],'LineWidth',2);
% 绘制小圆
sCircleHdl=plot(cos(thetaB)+CPnts(1,:),sin(thetaB)+CPnts(2,:),...
    'Color',[0.3098 0.5059 0.7412],'LineWidth',2);
% 绘制正内接多边形
pntsHdl=plot(cos(pntsTheta+thetaS)+cos(thetaB),...
    sin(pntsTheta+thetaS)+sin(thetaB),...
    'Color',[0.2157 0.3765 0.5725],'LineWidth',2,'Marker','o',...
    'MarkerFaceColor',[0 0 0],'MarkerEdgeColor',[0 0 0],'MarkerSize',6);

patchHdl=fill(cos(pntsTheta(1:end-1)+thetaS)+cos(thetaB),...
              sin(pntsTheta(1:end-1)+thetaS)+sin(thetaB),...
              [0.8500 0.3250 0.0980],'EdgeColor','none','FaceAlpha',0.1);
% 循环绘图
while 1
    thetaB=thetaB-2*pi/200;
    thetaS=thetaS+2*pi/200;
    sCircleHdl.XData=cos(thetaB)+CPnts(1,:);
    sCircleHdl.YData=sin(thetaB)+CPnts(2,:);
    pntsHdl.XData=cos(pntsTheta+thetaS)+cos(thetaB);
    pntsHdl.YData=sin(pntsTheta+thetaS)+sin(thetaB);
    patchHdl.XData=cos(pntsTheta(1:end-1)+thetaS)+cos(thetaB);
    patchHdl.YData=sin(pntsTheta(1:end-1)+thetaS)+sin(thetaB);
    pause(0.05);
end
end

李萨如图形

这个没啥好说的,画图好看就好hiahiahia:

可视化效果:
MATLAB | 三个趣的圆相关的数理性质可视化-LMLPHP

MATLAB代码:

function lissajous
% @author : slandarer
% 公众号  : slandarer随笔
% 知乎    : hikari

% figure及axes基础属性设置
fig=gcf;
fig.Position([2,4])=...
[fig.Position(2)-fig.Position(3)+fig.Position(4),fig.Position(3)];
%
ax=gca;hold on
ax.Color=[102,117,149]./255;
ax.XColor='none';ax.XLim=[.4,8.6];ax.YTick=[];
ax.YColor='none';ax.YLim=[.4,8.6];ax.XTick=[];
ax.DataAspectRatio=[1,1,1];
ax.InnerPosition=[0,0,1,1];

% 绘制圆圈
t=linspace(0,2*pi,200)';
X=cos(t).*0.42;Y=sin(t).*0.42;
plot(X+ones(1,7),Y+(1:7),'Color',[1,1,1,.7],'LineWidth',2);
plot(X+(2:8),Y+ones(1,7).*8,'Color',[1,1,1,.7],'LineWidth',2);
% 绘制点和基础线
[Xpnt,Ypnt]=meshgrid(2:8,1:7);
pntHdl=plot(Xpnt+0.42,Ypnt,'Color',[1,1,1],'LineStyle','none',...
    'Marker','o','MarkerFaceColor',[1,1,1]);
XlineCol=2:8;YlineCol=8.*ones(1,7);
XlineRow=ones(1,7);YlineRow=1:7;
lineColHdl=plot([XlineCol;Xpnt(1,:)]+0.42,[YlineCol;Ypnt(1,:)],...
    'Color',[1,1,1,.5],'LineStyle','-.','Marker','o','MarkerFaceColor',[1,1,1]);
lineRowHdl=plot([XlineRow;Xpnt(:,end)']+0.42,[YlineRow;Ypnt(:,end)'],...
    'Color',[1,1,1,.5],'LineStyle','-.','Marker','o','MarkerFaceColor',[1,1,1]);
% 绘制折线句柄
for m=1:7
    for n=1:7
        lineMatHdl(m,n)=plot(Xpnt(n,m),Ypnt(n,m),...
            'Color',[1,1,1,.6],'LineWidth',1.2);
    end
end
ratio=1:7;
thetaList=linspace(0,2*pi,300);
% 循环绘图
for i=1:length(thetaList)
    theta=thetaList(i).*ratio;
    tX=cos(theta).*0.42;
    tY=sin(theta).*0.42;
    for j=1:7
        pntHdl(j).XData=Xpnt(:,j)+tX(j);
        pntHdl(j).YData=Ypnt(:,j)+tY(end:-1:1)';
        lineColHdl(j).XData=[XlineCol(j);Xpnt(1,j)]+tX(j);
        lineColHdl(j).YData=[YlineCol(j);Ypnt(1,j)]+[tY(j);tY(7)];
        lineRowHdl(j).XData=[XlineRow(j);Xpnt(j,end)']+[tX(8-j);tX(7)];
        lineRowHdl(j).YData=[YlineRow(j);Ypnt(j,end)']+tY(8-j);
    end
    %
    ttList=thetaList(1:i);
    for m=1:7
        for n=1:7
            lineMatHdl(m,n).XData=cos(ttList.*m).*0.42+Xpnt(n,m);
            lineMatHdl(m,n).YData=sin(ttList.*(8-n)).*0.42+Ypnt(n,m);
        end
    end
    drawnow
    pause(.01)
end
end
06-25 07:22