三角形兩頂點在橢圓上滑動時第三點的軌跡

        受到《趣題:三角形兩頂點在直線上滑動時第三點的軌跡》(http://www.matrix67.com/blog/archives/2896)的啓發,決定研究一下三角形兩頂點在橢圓上滑動時第三點的軌跡。△ABC和△ABD的A、B兩點在橢圓x^2/a^2+y^2/b^2=1(a>b)上滑動,C和D兩點關於線段AB對稱,其中C點更靠近橢圓中心。C點不一定在橢圓內部,D點也不一定在橢圓外部。C、D兩點軌跡的參數方程比較容易得出,先假設A點的座標(Ax,Ay),Ax=acosθ,Ay=bsinθ,然後求以A爲圓心、AB長度爲半徑的圓與橢圓的交點(求解四次方程),即得B點座標。
    ■|AB|較小時,四次方程只有2個實根,可以得到2個B點;    
    ■|AB|較大時,四次方程可能出現4個實根,還可能有重根。(比如|AB|=2b,A位於橢圓短軸端點,B可以位於橢圓左側、右側以及另一個短軸端點,Bx=0就是二重根)
    ■|AB|=2a,則A、B分別位於2個長軸端點,三角形無法滑動。
    ■|AB|>2a,則A、B無法同時位於橢圓上。

       第一次解四次方程後,從實根中隨意選出一個作爲第一個B點的橫座標。那麼如何從之後解出的2個或4個實根中選出合適的根作爲下一個B點的橫座標呢?最直接的想法是要儘可能地靠近前一個B點。四次方程有2個實根時,在(Bx(1),±b*sqrt(1-Bx(1)^2/a^2)),(Bx(2),±b*sqrt(1-Bx(2)^2/a^2))這4個點中,只有2個點與A點的距離是|AB|,用
abs((NewBx-Ax)^2+(b*sqrt(1-NewBx^2/a^2)-Ay)^2-AB^2)<1e-8
這一條件就能選出2個正確的B點,在這2個正確的點中找出與前一個B點距離最近的,就是所需的下一個B點。不直接寫成
(NewBx-Ax)^2+(b*sqrt(1-NewBx^2/a^2)-Ay)^2==AB^2
是因爲浮點運算的誤差可能導致並不嚴格相等(誤差在1e-15量級)。四次方程有4個實根時,共有(Bx(1),±By(1)),(Bx(2),±By(2)),(Bx(3),±By(3)),(Bx(4),±By(4))8個可能的點,先從前4個可能點中選出一個距離最小的,再從後4個可能點中選出一個距離最小的,最後從這兩個距離“最小”的點中選出一個距離更小的。

       提供一個有4個實根的數值例子,a=2,b=1,|AB|=1.9,
A(2cos(1.31),sin(1.31))=A(0.515700,0.966185),B1(-1.369414,0.728818),B2(1.814578,-0.420507),B3(1.436365,-0.695855),B4(0.868872,-0.900703)。

MATLAB代碼

clc;close all;
tic
global a b AB
a=2; b=1; 
AB=1.90;BC=0.7;AC=1.3;
cos_BAC=(AB^2+AC^2-BC^2)/(2*AB*AC); %餘弦定理
sin_BAC=sqrt(1-cos_BAC^2);
N=629;
Bpoint=zeros(2,N);  Cpoint=zeros(2,N);  Dpoint=zeros(2,N);

int1=1;
QA=int1/100;
Ax=a*cos(QA);
Ay=b*sin(QA);
T=Ax^2+Ay^2+b^2-AB^2;
root4=roots([(b^2/a^2 - 1)^2, 4*Ax*(b^2/a^2 - 1), 4*Ax^2 - 2*T*(b^2/a^2 - 1)...
    + (4*Ay^2*b^2)/a^2, -4*Ax*T,- 4*Ay^2*b^2 + T^2]);
Bx=zeros(2,1);
[Bx(1),Bx(2)]=SelectRealRoot(root4);
Bpoint(1,int1)=Bx(1);
if abs((Bx(1)-Ax)^2+(b*sqrt(1-Bx(1)^2/a^2)-Ay)^2-AB^2)<1e-8
    Bpoint(2,int1)=b*sqrt(1-Bx(1)^2/a^2); 
else
    Bpoint(2,int1)=-b*sqrt(1-Bx(1)^2/a^2);
end

ABvector=[Bpoint(1,int1)-Ax,Bpoint(2,int1)-Ay];
ACvector=ABvector*AC/AB*[cos_BAC,sin_BAC;-sin_BAC,cos_BAC]; %實現向量的旋轉
ADvector=ABvector*AC/AB*[cos_BAC,-sin_BAC;sin_BAC,cos_BAC];
if ((Ax+ACvector(1))^2+(Ay+ACvector(2))^2)>((Ax+ADvector(1))^2+(Ay+ADvector(2))^2)
    %假定C點更靠近橢圓中心,這與選擇第一個B點的座標一樣,具有一定的隨機性。
    TempVector=ACvector;
    ACvector=ADvector;
    ADvector=TempVector;
end
Cpoint(:,int1)=[Ax+ACvector(1);Ay+ACvector(2)];
Dpoint(:,int1)=[Ax+ADvector(1);Ay+ADvector(2)];

for int1=2:N
     int1 %顯示int1監測進度
% QA=0.01:0.01:2*pi
QA=int1/100;
Ax=a*cos(QA);
Ay=b*sin(QA) ;
T=Ax^2+Ay^2+b^2-AB^2;
root4=roots([(b^2/a^2 - 1)^2, 4*Ax*(b^2/a^2 - 1), 4*Ax^2 - 2*T*(b^2/a^2 - 1)...
           + (4*Ay^2*b^2)/a^2, -4*Ax*T, - 4*Ay^2*b^2 + T^2]);

if abs(imag(root4(1)))<1e-8 && abs(imag(root4(2)))<1e-8  && ...
   abs(imag(root4(3)))<1e-8 && abs(imag(root4(4)))<1e-8  %如果有4個實根
        root4
   [Bx(1),~]=...
   DetermineBpoint(root4(1),root4(2),Bpoint(1,int1-1),Bpoint(2,int1-1),Ax,Ay); 
   [Bx(2),~]=...
   DetermineBpoint(root4(3),root4(4),Bpoint(1,int1-1),Bpoint(2,int1-1),Ax,Ay); 
else %如果有2個實根
   [Bx(1),Bx(2)]=SelectRealRoot(root4);
end
   [Bpoint(1,int1),Bpoint(2,int1)]=...
    DetermineBpoint(Bx(1),Bx(2),Bpoint(1,int1-1),Bpoint(2,int1-1),Ax,Ay); 

    ABvector=[Bpoint(1,int1)-Ax,Bpoint(2,int1)-Ay];
    ACvector=ABvector*AC/AB*[cos_BAC,sin_BAC;-sin_BAC,cos_BAC]; %實現向量的旋轉
    ADvector=ABvector*AC/AB*[cos_BAC,-sin_BAC;sin_BAC,cos_BAC];
    if ((Ax+ACvector(1))^2+(Ay+ACvector(2))^2)>((Ax+ADvector(1))^2+(Ay+ADvector(2))^2)
        %因爲C點更靠近橢圓中心
        TempVector=ACvector;
        ACvector=ADvector;
        ADvector=TempVector;
    end
    Cpoint(:,int1)=[Ax+ACvector(1);Ay+ACvector(2)];
    Dpoint(:,int1)=[Ax+ADvector(1);Ay+ADvector(2)];
end

LWidth=1;
for int1=1:30:N
    QA=int1/100;
    Ax=a*cos(QA);
    Ay=b*sin(QA); 
    ColorArray=[mod(5*int1,N)/N,mod(10*int1,N)/N,mod(15*int1,N)/N];
    line([Ax,Bpoint(1,int1)],[Ay,Bpoint(2,int1)],'color',ColorArray,'LineWidth',LWidth); hold on
    line([Ax,Cpoint(1,int1)],[Ay,Cpoint(2,int1)],'color',ColorArray,'LineWidth',LWidth); 
    line([Cpoint(1,int1),Bpoint(1,int1)],[Cpoint(2,int1),Bpoint(2,int1)],'color',ColorArray,'LineWidth',LWidth); 
    line([Ax,Dpoint(1,int1)],[Ay,Dpoint(2,int1)],'color',ColorArray,'LineWidth',LWidth); 
    line([Dpoint(1,int1),Bpoint(1,int1)],[Dpoint(2,int1),Bpoint(2,int1)],'color',ColorArray,'LineWidth',LWidth); 
end

plotEllipse=plot(a*cos(0:0.01:2*pi),b*sin(0:0.01:2*pi),'LineWidth',2,'color',[0,0,0]);hold on
plotC=plot(Cpoint(1,:),Cpoint(2,:),'LineWidth',2,'color',[1,0,0]);
plotD=plot(Dpoint(1,:),Dpoint(2,:),'LineWidth',2,'color',[0,0,1]);
legend([plotEllipse,plotC,plotD],{'橢圓x^2/a^2+y^2/b^2=1','C點軌跡','D點軌跡'})
title(strcat('a=',num2str(a),', b=',num2str(b),'; AB=',num2str(AB),...
    ', BC=',num2str(BC),', AC=',num2str(AC),'; 作者:磁懸浮青蛙呱呱呱'))
h=max([AB,AC,BC])+0.1;
axis([-(a+h),a+h,-(b+h),b+h]);axis equal
hold off
toc 

function [Bx1,Bx2]=SelectRealRoot(root4)
int3=1;
Bx=zeros(2,1);
    for int2=1:4   %從4個根中挑選出2個實根
        if abs(imag(root4(int2)))<1e-8
           Bx(int3)= root4(int2);
           int3=int3+1;
        end
    end
Bx1=Bx(1);
Bx2=Bx(2);
end

function [Bx,By]=DetermineBpoint(NewBx1,NewBx2,PreviousBx,PreviousBy,Ax,Ay)
global a b AB
BTemp=zeros(2,2);
int2=1;

    if  abs((NewBx1-Ax)^2+(b*sqrt(1-NewBx1^2/a^2)-Ay)^2-AB^2)<1e-8
        BTemp(:,int2)=[NewBx1;b*sqrt(1-NewBx1^2/a^2)];
        int2=int2+1;
    end
    if  abs((NewBx1-Ax)^2+(-b*sqrt(1-NewBx1^2/a^2)-Ay)^2-AB^2)<1e-8
        BTemp(:,int2)=[NewBx1;-b*sqrt(1-NewBx1^2/a^2)];
        int2=int2+1;
    end    
    if  abs((NewBx2-Ax)^2+(b*sqrt(1-NewBx2^2/a^2)-Ay)^2-AB^2)<1e-8
        BTemp(:,int2)=[NewBx2;b*sqrt(1-NewBx2^2/a^2)];
        int2=int2+1;
    end    
    if  abs((NewBx2-Ax)^2+(-b*sqrt(1-NewBx2^2/a^2)-Ay)^2-AB^2)<1e-8
        BTemp(:,int2)=[NewBx2;-b*sqrt(1-NewBx2^2/a^2)];
    end
    
    if norm(BTemp(:,1)-[PreviousBx;PreviousBy])<norm(BTemp(:,2)-[PreviousBx;PreviousBy])
        Bx=BTemp(1,1); By=BTemp(2,1);  return;
    else
        Bx=BTemp(1,2); By=BTemp(2,2);
    end
end

       下面給出的C、D兩點的軌跡圖,主要是0<|AB|<2b情況下的,其它情形可自行研究。觀察下面這些軌跡圖,當|AC|=|BC|時,C點和D點的軌跡存在兩根相互垂直的對稱軸。|AC|≠|BC|時,C點和D點的軌跡不存在對稱軸,而是一箇中心對稱圖形。

等邊三角形

等腰三角形

銳角不等腰三角形

直角三角形

鈍角三角形

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章