Code covered by the BSD License  

Highlights from
plt

image thumbnail
from plt by Paul Mennen
An alternative to plot and plotyy optimized for data exploration

curves(In)
% curves.m ----------------------------------------------------------
% This function shows an example (a bit contrived perhaps) where
% many GUI controls need to be crowded into a relatively small space.
% The ten controls above the graph (nine edit text objects and one
% popup text object) all are used to control how the parametric
% curves in the graph are displayed. If we used the traditional
% MatLab GUI objects, we would have had to make the graph much
% smaller to make room for all these controls. In addition, the
% plt('edit') objects provide a much easier way to modify the
% numeric values nearly matching the convenience of a slider object.
%
% After starting curves.m, right click on the curve name at the
% bottom of the figure to cycle thru the 36 different cool looking
% curve displays. (Left click on the curve name as well to select
% from the complete list of curves.) The equations in white above
% the curve name, are not only used as the x-axis label. These are
% the exact equations that are used to compute the points plotted
% on the graph. The vector t, and the constants a, b, and c that
% appear in these equations are defined by the controls above the
% graph. Experiment by both right and left clicking on these
% controls. For the cases when more than one trace is plotted, the
% first control on the left (called trace) indicates which trace is
% effected by the other nine controls above the graph. Note that
% when you left click on a control, it will increase or decrease
% depending on whether you click on the left or right side of the
% text string. Separate values for a, b, and c are saved for each
% trace of a multi-trace plot. This explains the variety of curves
% that can appear for a single set of equations (shown below the
% graph). 

% ----- Author: ----- Paul Mennen
% ----- Email:  ----- paul@mennen.org

function Out = curves(In)

qName = 1;  % define columns of CRq
qT    = 2;
qXlim = 3;
qYlim = 4;
qa    = 5;
qb    = 6;
qc    = 7;
qSty  = 8;
qXoff = 9;
qYoff = 10;
qEval = 11;

TXtrc = 1;  % define user edit strings
TXa   = 2;
TXb   = 3;
TXc   = 4;
TXxof = 5;
TXyof = 6;
TXstp = 7;
TXtmn = 8;
TXtmx = 9;
TXsty = 10;
startIdx = 31; % select the Spirograph curves as the initial choice

if ~nargin
  % Curve Name             [n tmin tmax]  Xlim        Ylim        a                   b                 c             Style         Xoffset             Yoffset
  P2 = 2*pi;
  CRq = ...
  {'Arachnida            ' [196 0 P2]     [-5.6 1.2]  [-1.4 1.4]  [2 3 5]             [3 2 4]           0             [1 8 1]       [0 -2 -4]           0                   ...
                           'r=sin(a*t)./sin(b*t);; x=r.*cos(t); y=r.*sin(t);';
   'Archimedian Spiral   ' [800 0 8*pi]   [-26 47]    [-29 23]    [-1 -2 1 2]         [30 600 1 .05]    0             1             [30 30 0 0]         [10 10 0 0]         ...
                           'r=b.*t.^a;; x=r.*cos(t); y=r.*sin(t);';
   'Bell curve           ' [800 -4 4]     [-4 4]      [-.1 1.1]   [5 7 10 15 20 25]   0                 0             1             0                   0                   ...
                           'x=t; a=a/10; y=exp(-x.^2/(2*a.^2));';
   'Bicuspid curve       ' [9999 -1 1]    [-1.7 1.7]  [-1.2 1.2]  [1 1 -1 -1]         [1 -1 1 -1]       0             9             0                   0                   ...
                           'x=a*sqrt(1+b*sqrt((1-t).^2.*(1-t.^2))); y=-t;; y(find(imag(x)))=Inf;';
   'Bullet nose          ' [300 0 P2]     [-9 9]      [-1.1 1.1]  [3 4 5 6 8 10]      0                 0             3             0                   0                   ...
                           'x=a*cot(t); y=cos(t);; y(find(abs(t-pi)<1e-6))=Inf;';
   'Butteryfly curve     ' [2000 0 24*pi] [-3.9 3.9]  [-2.8 4.2]  24                  5                 4             1             0                   0                   ...
                           'r=exp(sin(t))-2*cos(c*t)+sin((2*t-pi)/a).^b;; x=r.*cos(t); y=r.*sin(t);';
   'Catenary             ' [200 -pi pi]   [-1.7 1.7]  [-.1 6]     [15 10 7 4 2 1]     0                 0             [1 1 1 1 1 6] 0                   0                   ...
                           'a=a/10; x=t; y=a*cosh(t/a);';
   'Cissoid of Diocles   ' [800 1.9 4.4]  [-.3 10.2]  [-13 13]    [5 6 7 8 9 10]      0                 0             1             [0 .5 1 1.5 2 2.5]  0                   ...
                           'r=a*tan(t).*sin(t);; x=r.*cos(t); y=r.*sin(t);';
   'Cochleoid            ' [800 0 8*pi]   [-.25 1.05] [-.1 .8]    0                   0                 0             1             0                   0                   ...
                           'r=sin(t)./t;; x=r.*cos(t); y=r.*sin(t);';
   'Cocked hat curve     ' [800 0 8*pi]   [-1.5 1.5]  [-3.5 14]   [-2 -1 0 1 2 5]     0                 0             1             0                   [0 1.5 3 4.5 6 7]   ...
                           'x=sin(t); y=cos(t).^2.*(a+cos(t))./(1+sin(t).^2);';
   'Conchoid of Nicomedes' [800 0 P2]     [-15 15]    [-3.3 5.4]  [4 3 2 1 2 1]       [1 1 1 1 3 2]     0             1             0                   0                   ...
                           'r=a+b*csc(t);; x=r.*cos(t); y=r.*sin(t);';
   'Cranioid             ' [800 0 P2]     [-17 17]    [-9 21]     6                   13                16            8             0                   0                   ...
                           'r=a*sin(t)+b*sqrt(1-c*cos(t).^2/20);; x=r.*cos(t); y=r.*sin(t);'
   'Cycloid              ' [800 0 18]     [1.7 16]    [-2.3 5.3]  [10 7 4 13 16 -10]  [10 7 4 13 16 10] 0             [8 3 3 1 1 8] 0                   [3 .5 1 2 -1 -2]    ...
                           'x=t-a*sin(t)/10; y=1-b*cos(t)/10;'
   'Devil''s curve       ' [800 0 P2]     [-3 3]      [-3 3]      [1 1 1 1 2 3]       [1.4 2 3 4 3 4]   0             1             0                   0                   ...
                           'v=sin(t).^2; w=cos(t).^2; r=sqrt((a*v-b*w)./(v-w));; x=r.*cos(t); y=r.*sin(t);'
   'Dumbbell curve       ' [801 -1 1]     [-2 2]      [-.6 2]     [0 23 7 30 37 53]   0                 0             1             [0 1 -1 0 -1 1]     [0 1 1 0 1 1]       ...
                           'r=sqrt(t.^2+t.^4-t.^6); w=acos(t./r)+(a*pi/30); x=r.*cos(w); y=r.*sin(w);'
   'Ellipse & evolute    ' [800 0 6*pi]   [-31 31]    [-1.1 1.1]  [30 27 24 21 18 15] 0                 0             1             0                   0                   ...
                           'v=bitor(floor(t/pi),1); x=a.*cos(t).^v; y=sin(t).^v;';
   'Epispiral            ' [800 0 P2]     [-25 25]    [-13 13]    [2 3 4]             11                0             [1 8 1]       [-16 -3 14]         0                   ...
                           'r=abs(sec(a*t));; x=r.*cos(t); y=r.*sin(t); y(find(abs(complex(x,y))>b))=Inf;';              
   'Epitrochoid          ' [800 0 10*pi]  [-38 36]    [-22 29]    [8 5 14 2 2 2]      [5 3 1 1 2 3]     [5 5 1 1 2 3] [1 1 6 1 8 1] [-18 18 18 1 -16 2] [0 0 0 -15 0 19]    ...
                           'w=(1+a/b)*t; x=(a+b)*cos(t)-c*cos(w); y=(a+b)*sin(t)-c*sin(w);'
   'Euler''s spiral      ' [600 -6 6]     [-1.1 1.1]  [-.77 .77]  0                   0                 0             1             0                   0                   ...
                           '[x y] = fresnel(t);';
   'Fish Curve           ' [300 0 P2]     [-1.24 1.2] [-.7 .7]    1                   0                 0             11            0                   0                   ...
                           'p=sin(t); q=cos(t); x=a*q-a*p.^2/sqrt(2); y=a*p.*q;';
   'Folium of Descartes  ' [801 -6 6]     [-3.2 3.7]  [-2.9 2.5]  1                   0                 0             8             0                   0                   ...
                           't=t.^3; v=1+t.^3; x=3*a*t./v; y=3*a*t.^2./v;';
   'Fourier Series       ' [800 -2 12]    [-2 12]     [-2.5 11.5] [2 2 1 2 4 1]       [1 0 1 1 1 1]     [2 1 1 1 1 2] [1 1 8 1 1 8] 0                   [10 7.6 4.4 2.2 0 -1.2] ...
                           'x=t; v=0:25; w=1+a*v; v=b*v; y=((-1).^v./(w.^c))*sin(w''*t);';
   'Gear Curve           ' [800 0 P2]     [-3 3]      [-2.2 2.2]  [1 1.4 1.8]         8                 [4 9 15]      1             0                   0                   ...
                           'r=a+tanh(b*sin(c*t))/b;; x=r.*cos(t); y=r.*sin(t);';
   'Hypocycloid          ' [800 0 14*pi]  [-11 8]     [-6 6]      [3 5 4 5 pi]        [1 1 1 3 1]       0             [8 1 1 1 1]   [6 0 -7 0 -7]       0                   ...
                           'v=a-b; p=t*v/b; x=v*cos(t)-b*cos(p); y=v*sin(t)+b*sin(p);';
   'Limacon              ' [200 0 P2]     [-40 150]   [-80 80]    [48 42 20 3]        [48 32 40 48]     0             [1 8 1 1]     [-15 0 0 85]        0                   ...
                           'r=a+b*cos(t);; x=r.*cos(t); y=r.*sin(t);';
   'Lissajous curves     ' [400 0 P2]     [-9 11]     [-1.2 1.2]  [1 5 1 1]           [2 4 2 3]         [99 99 2 1]   [1 1 8 8]     [6 0 -7 9]          0                   ...
                           'x=a.*sin(b*t+pi/c); y=sin(t);';
   'Maclaurin Trisectrix ' [800 1.8 4.5]  [-.9 1.6]   [-1.5 1.5]  [-5 -3 -1 1 3 5]    0                 0             1             0                   0                   ...
                           'r=sin(3*t)./sin(2*t); w=t+a*pi/60; x=r.*cos(w); y=r.*sin(w);';
   'Rose                 ' [800 0 14*pi]  [-3 3.1]    [-2.1 2]    [2 3 4 1 2 exp(1)]  [1 1 1 3 3 1]     0             1             [-2 0 2 -2 0 2]     [1 1.2 1 -.8 -1 -1] ...
                           'r=sin(a*t/b);; x=r.*cos(t); y=r.*sin(t);';
   'Scarabaeus           ' [800 0 P2]     [-6 12]     [-4 4]      [2 3 1 1]           [3 2 1 3]         [2 2 2 7]     1             [0 6 4 11]          0                   ...
                           'r=a*cos(c*t)-b*cos(t);; x=r.*cos(t); y=r.*sin(t);';
   'Serpentine curve     ' [800 -9 9]     [-9 9]      [-.6 .6]    [1 2 3 4 5 6]       0                 0             1             0                   0                   ...
                           'x=t; y=a*x./(a^2+x.^2);';
   'Spirograph           ' [800 0 P2]     [-3 17]     [-5 9]      [3 10 10 7 14 5]    [1 1 1 2 2 3]     [2 3 4 4 6 6] [6 1 1 1 1 8] [0 6 13 0 6 13]     [6 6 6 0 0 0]       ...
                           'x=b*cos(t)+a*cos(c*t)/10; y=b*sin(t)-a*sin(c*t)/10;';
   'Square wave          ' [400 -2 8]     [-2 8]      [-1.3 6.5]  [6 5 4 3 2 1]       0                 0             1             0                   [0 1 2 3 4 5]       ...
                           'x=t; v=1 : 2 : 2*a-1; y=4./(pi*v)*sin(v''*t);';
   'Strophoid            ' [800 0 P2]     [-7.4 13.4] [-15 15]    [8 9 10 11 12 13]   0                 0             1             0                   0                   ...
                           'r=a*cos(2*t).*sec(t);; x=r.*cos(t); y=r.*sin(t);';
   'Talbot''s curve      ' [800 0 P2]     [-16 110]   [-15 15]    [4 5 6 7 8 9]       13                0             1             [0 23 40 60 80 99]  0                   ...
                           's=sin(t); c=a^2-b^2; x=(a^2+c*s.^2).*cos(t)/a; y=(a^2-2*c+c*s.^2).*s/b;';
   'Teardrop             ' [400 0 P2]     [-1.1 1.1]  [-.9 .9]    [16 11 7 4 2 1]     0                 0             [1 1 1 1 1 8] 0                   0                   ...
                           'x=cos(t); y=sin(t).*sin(t/2).^a;';
   'Witch of Agnesi      ' [800 -4 4]     [-4 4]      [0 5.6]     [3 3.5 4 4.5 5 5.5] 0                 0             1             0                   0                   ...
                           'x=t; y=a./(1+x.^2);'
  };

  names = CRq(:,1);
  for k=1:length(names)
    sz = length(CRq{k,qa});
    for m=qb:qYoff % expand shorter vectors to the size of a
      if length(CRq{k,m})<sz CRq{k,m} = zeros(1,sz)+CRq{k,m}; end;
    end;
  end;
  CRlines = plt(1,ones(1,6),'LabelX','','Position',[10 45 930 680],...
                            'FigBKc',[.1 .2 .1],'Options','Ticks-X-Y',...
                            'FigName','Curves','AxisPos',[1 1.45 1 .9 1 .9 1 1]);
  ax = gca;
  set(ax,'TickLen',[0 0]);
  CRb = flipud(get(findobj(gcf,'user','TraceID'),'child'));
  xl = get(ax,'Xlabel');
  fontsz = get(xl,'fontsize');  set(xl,'fontsize',1.4*fontsz,'color','white');
  tx = {'Trace' 'a' 'b' 'c' 'Xoffset' 'Yoffset' 't Steps' 't Min' 't Max' 'Style' };
  x = 0;
  for k=1:length(tx)
    text(0,0,tx{k},'units','norm','pos',[x 1.07],'color',[.8 .8 .8],'horiz','center');
    cb = ['curves(' int2str(k) ')'];
    if k==TXsty
         CRi(k) = plt('pop','offset',[-.015 -.47],'choices',...
            {' line';' --';' :';' -.';' +';' o';' *';' .';' x';' s';' d';' ^';' v';' >';' <';' p';' h'},...
            'callbk',cb,'horiz','center','location',[x-.012 .943 .042 .5]);
    else CRi(k) = plt('edit','units','norm','position',[x 1.035],'callbk',cb);
    end;
    x = x + .1;
  end;
  plt('edit',CRi(TXtrc),'min',1);
  axes(ax);
  CRa = text(0,0,'\leftarrow right click on curve name',...
       'fontsize',1.4*fontsz,'color',[0 1 1],'units','norm','pos',[.35 -.135]);
  CRp = plt('pop','choices',CRq(:,1),'index',31,'location',[.27 .01 .24 1],...
            'fontsize',2*fontsz,'callbk','curves(0)');
  set(gcf,'user',{CRlines CRq CRp CRi CRa CRb});
  curves(0);
else
  a = get(gcf,'user');
  CRlines = a{1};  CRq = a{2};  CRp = a{3};  CRi = a{4};  CRa = a{5};  CRb = a{6};
  cs = plt('pop',CRp,'get','index');
  if cs ~= startIdx set(CRa,'visible','off'); end;
  tr = plt('edit',CRi(1),'get','value');
  if In<=TXtrc  % here for curve name and trace number callbacks
    if ~In      % if curve callback, reset to trace number 1
      tr = 1;  plt('edit',CRi(1),'value',1,'max',length(CRq{cs,qa}));
      plt('edit',CRi(TXstp),'value',CRq{cs,qT}(1));
      plt('edit',CRi(TXtmn),'value',CRq{cs,qT}(2));
      plt('edit',CRi(TXtmx),'value',CRq{cs,qT}(3));
    end;
    plt('edit',CRi(TXa),  'value',CRq{cs,qa}(tr));
    plt('edit',CRi(TXb),  'value',CRq{cs,qb}(tr));
    plt('edit',CRi(TXc),  'value',CRq{cs,qc}(tr));
    plt('edit',CRi(TXxof),'value',CRq{cs,qXoff}(tr));
    plt('edit',CRi(TXyof),'value',CRq{cs,qYoff}(tr));
    plt('pop', CRi(TXsty),'index',CRq{cs,qSty}(tr));
  else
    if In==TXsty CRq{cs,qSty}(tr) = plt('pop',CRi(In),'get','index');
    else  v = plt('edit',CRi(In),'get','value');
          switch In
            case TXa,   CRq{cs,qa}(tr)    = v;
            case TXb,   CRq{cs,qb}(tr)    = v;
            case TXc,   CRq{cs,qc}(tr)    = v;
            case TXxof, CRq{cs,qXoff}(tr) = v;
            case TXyof, CRq{cs,qYoff}(tr) = v;
            case TXstp, CRq{cs,qT}(1)     = v;
            case TXtmn, CRq{cs,qT}(2)     = v;
            case TXtmx, CRq{cs,qT}(3)     = v;
          end % end switch In
    end;      % if In==TXsty
  end;        % end if In<=TXtrc
  ax = get(CRlines(1),'parent');
  tiny = 1e-32;
  t = CRq{cs,qT};
  step = (t(3)-t(2))/t(1);  t = tiny + t(2):step:t(3);
  set(ax,'xlim',CRq{cs,qXlim},'ylim',CRq{cs,qYlim});
  aa = CRq{cs,qa}; bb = CRq{cs,qb}; cc = CRq{cs,qc};
  Xoff = CRq{cs,qXoff}; Yoff = CRq{cs,qYoff};  Style = CRq{cs,qSty};
  StyCH = plt('pop',CRi(TXsty),'get','choices');
  n = length(aa);
  set(CRlines,'x',0,'y',0);
  func = CRq{cs,qEval};
  f = ['\bf' func];  p = findstr(f,';;');
  if length(p) f = f(1:p(1));  end;
  f1 = {'.'   ';'            '='        '*'         '+'     '-'     '/'  };
  f2 = {''    '       \bf'   ' = \rm'   ' \cdot '   ' + '   ' - '   ' / '};
  for k=1:length(f1) f=strrep(f,f1{k},f2{k}); end;
  set(get(ax,'Xlabel'),'str',f);
  for m = 1:n
    a = aa(m);  b = bb(m);  c = cc(m);  STYix = Style(m);
    if STYix==1  sty = '-'; else  sty = StyCH{STYix}; end;
    if STYix<5 mrk = 'none'; else mrk = sty;  sty = 'none'; end;
    eval(func);
    set(CRlines(m),'x',x+Xoff(m),'y',y+Yoff(m),'Marker',mrk,'LineStyle',sty);
    s = ['trace ' int2str(m)];
    if m==tr & n>1 s = [s '<<']; end;
    set(CRb(m),'string',s);
  end;
  for m = (n+1):6 set(CRb(m),'string',''); end;

  plt('grid',ax);
end; % end if ~nargin
%end function curves

function [fcos,fsin]=fresnel(xx) % computes the cos and sin fresnel integrals
acc = 1e-15;                   % accuracy required
sx = sign(xx);  xx = abs(xx);  % apply signs at the end
fcos = xx;  fsin = xx;         % pre-allocate outputs
for n = 1:length(xx)
  x = xx(n);
  px = pi*x;  t = px*x/2;  t2  = -t.^2;
  if    ~x    c=0; s=0;
  elseif x < 2.5
    r = x;   c = r;
    for  k=1:50  r = r * t2 * (4*k-3) / polyval([16 -4 -2 0],k);
                 c = c + r;
                 if abs(r) < abs(c)*acc  break; end;
    end;
    s = x*t/3;  r = s;
    for  k=1:50  r = r * t2 * (4*k-1) / polyval([16 20 6 0],k);
                 s = s + r;
                 if abs(r) < abs(s)*acc break; end;
    end;
  elseif x < 4.5;
    m = fix(42 + 1.75*t);
    su = 0;  c = 0;  s = 0;  f1 = 0;  f0 = 1e-100;
    for  k = m:-1:0  f = (2*k+3) * f0 / t - f1;
                     if mod(k,2)  s=s+f;  else  c=c+f;  end;
                     su = su + (2*k+1) * f^2;  f1 = f0;  f0 = f;
    end;
    q = sqrt(su);  c = c*x/q;   s=s*x/q;
  else;
    r = 1;  f = 1;
    for k=1:20   r = r * polyval([1 -1 .75],k) / t2;
                 f = f + r;
    end;
    r = 1 / (px*x);
    g = r;
    for k=1:12   r = r * polyval([1 0 -.0625],k) / t2;
                 g = g + r;
    end;
    t0 = t - fix(t/(2*pi)) * 2*pi;
    c  = .5 + (f*sin(t0) - g * cos(t0)) / px;
    s  = .5 - (f*cos(t0) + g * sin(t0)) / px;
  end;  % end if ~x
  fcos(n) = c;  fsin(n) = s;
end;    % end for n = 1:length(xx)
fcos = sx .* fcos;
fsin = sx .* fsin;
% end function fresnel

Contact us at files@mathworks.com