1 %{
  2   Finds closest point on a ellipse, for two cases,
  3   to a given point.
  4   Case 1: Ellipse is a circle.  Point is outside or
  5   inside of ellipse.
  6   Case 2: Ellipse centered at origin with major
  7   and minor axes the x and y axes, and given point
  8   outside the ellipse.
  9   Octave 5.1.0
 10   John Bryan 2019
 11 %}
 12 
 13 echo off;
 14 close all;
 15 clear all;
 16 clear;clf
 17 graphics_toolkit fltk
 18 
 19 function Case2Plot(x0,y0,a,b,c,d,Cx,Cy,m,filename)
 20    figure (m);
 21    x0=0; % horizontal center coordinate
 22    y0=0; % vertical center coordinate
 23    t=-pi:0.01:pi;
 24    x=x0+acos(t);
 25    y=y0+bsin(t);
 26    plot(x,y)
 27    hold on
 28    plot(Cx,Cy,"","markersize",5,"markerfacecolor","auto");
 29    plot(c,d,"","markersize",5,"markerfacecolor","auto");
 30    text(c,d,['(' num2str(c,"%3.2f") ',' num2str(d,"%3.2f") ')'])
 31    text(Cx,Cy,['(' num2str(Cx,"%3.2f") ',' num2str(Cy,"%3.2f") ')'])
 32    xmin=findmin(-a,c)-2;
 33    xmax=findmax(a,c)+2;
 34    ymin=findmin(-b,d)-2;
 35    ymax=findmax(b,d)+2;
 36    axis([xmin xmax ymin ymax]);
 37    set(gcf,'InvertHardCopy','off')
 38    print (gcf, "-S500,500", filename, '-dpng')
 39 endfunction
 40 
 41 function Case1Plot(Ax,Ay,Bx,By,Cx,Cy,r,N,i,filename)
 42     figure (i);
 43     theta=2pi*linspace(0,1,200);
 44     xc=Ax+rcos(theta);
 45     yc=Ay+rsin(theta);
 46     plot([Ax Bx],[Ay By])
 47     hold on;
 48     plot(Ax,Ay,"","markersize",7,"markerfacecolor","auto");
 49     plot(Bx,By,"","markersize",7,"markerfacecolor","auto");
 50     plot(Cx,Cy,"","markersize",7,"markerfacecolor","auto");
 51     h=plot(xc,yc,'linewidth',1);
 52     plot([Ax Bx],[Ay By])
 53     text(Ax,Ay,['(' num2str(Ax) ',' num2str(Ay) ')'])
 54     text(Bx,By,['(' num2str(Bx) ',' num2str(By) ')'])
 55     text(Cx,Cy,['(' num2str(Cx,"%3.2f") ',' num2str(Cy,"%3.2f") ')'])
 56     xmin=findmin(Ax-r,Bx)-1;
 57     xmax=findmax(Ax+r,Bx)+1;
 58     ymin=findmin(Ay-r,By)-1;
 59     ymax=findmax(Ay+r,By)+1;
 60     axis([xmin xmax ymin ymax]);
 61     axis equal;
 62     set(gcf,'InvertHardCopy','off')
 63     print (gcf, "-S500,500", filename, '-dpng')
 64 endfunction
 65 
 66 function xin = CalculateInitialGuess(c,d,a,b)
 67     if (a>b) r=a; else r=b; endif;
 68     [Cx,Cy]=CalculateCirclePoint(0,0,c,d,r);
 69     xin=Cx;
 70     return;
 71 endfunction
 72 
 73 function [Ex,Ey]=CalculateCirclePoint(Dx,Dy,Px,Py,r)
 74     magPD=sqrt((Px-Dx)^2+(Py-Dy)^2)
 75     if ((Px-Dx)==0) Ex=Dx;
 76     else Ex=Dx+(r(Px-Dx)/magPD); endif;
 77     if ((Py-Dy)==0) Ey=Dy;
 78     else Ey=Dy+(r(Py-Dy)/magPD); endif;
 79 endfunction
 80 
 81 function max0 = findmax(a,b)
 82     if(a > b)
 83        max0=a;
 84        return;
 85     else
 86        max0=b;
 87        return;
 88     endif
 89 endfunction
 90 
 91 function min0 = findmin(a,b)
 92     if(a < b)
 93        min0=a;
 94        return;
 95     else
 96        min0=b;
 97        return;
 98     endif
 99 endfunction
100 
101 function Case1
102   N=4;
103   D_x=[0, 3, -2, 1];
104   D_y=[0, -1, 3, 2];
105   P_x=[5, 2, -3, 3];
106   P_y=[3, 1, -1, 2];
107   radius=[1, 2, 3, 4];
108   for i=[1:1:N]
109       Dx=D_x(i);
110       Dy=D_y(i);
111       Px=P_x(i);
112       Py=P_y(i);
113       r=radius(i);
114       [Ex,Ey]=CalculateCirclePoint(Dx,Dy,Px,Py,r)
115       filename=["plot" int2str(i) ".png"]
116       Case1Plot(Dx,Dy,Px,Py,Ex,Ey,r,N,i,filename);
117   endfor
118 endfunction
119 
120 function Case2
121   C=[3, -4, -4, 5];
122   D=[3, 3, -3, -4];
123   A=[2, 1, 3, 2];
124   B=[1, 2, 1, 3];
125   N=4;
126   for m=[N+1:1:N+4]
127      c=C(m-N)
128      d=D(m-N)
129      a=A(m-N)
130      b=B(m-N)
131      x=zeros(1,20);
132      xin = CalculateInitialGuess(c,d,a,b)
133      x(1)=xin;
134      for n=[1:1:20]
135         x0=x(n);
136         fterm1num=b^2d*x0;
137         fterm1den=(b^2-a^2)x0+a^2*c;
138         fterm1=fterm1num/fterm1den;
139         if (d<0)
140            fterm2=bsqrt(1-x0^2/a^2);
141         else
142            fterm2=-bsqrt(1-x0^2/a^2);
143         endif
144         f=fterm1+fterm2;
145         fpterm1num=b^2d*((b^2-a^2)*x0+a^2*c)-b^2*d*x0*(b^2-a^2);
146         fpterm1den=((b^2-a^2)x0+a^2*c)^2;
147         fpterm1=fpterm1num/fpterm1den;
148         if (d<0)
149            fpterm2=-(2b*x0)/(a^2*sqrt(1-x0^2/a^2));
150         else
151            fpterm2=(2b*x0)/(a^2*sqrt(1-x0^2/a^2));
152         endif
153         fp=fpterm1+fpterm2;
154         x(n+1)=x(n)-f/fp;
155         f
156      endfor
157      x
158      x20=real(x(20))
159      if (d<0)
160         y20=-bsqrt(1-x20^2/a^2)
161      else
162         y20=bsqrt(1-x20^2/a^2)
163      endif
164      Ex=x20;
165      Ey=y20;
166      filename=["ellipseplot" int2str(m) ".png"]
167      Case2Plot(0,0,a,b,c,d,Ex,Ey,m,filename)
168      minus1_ProductOfSlopes_check=-(b^2Ex*(Ey-d))/(a^2*Ey*(Ex-c))
169   endfor
170 endfunction
171 
172 Case1
173 Case2