splinetool.m

来自「演示matlab曲线拟和与插直的基本方法」· M 代码 · 共 1,585 行 · 第 1/5 页

M
1,585
字号
function splinetool(x,y)
%SPLINETOOL Spline approximation experimentation tool (GUI).
%
%   SPLINETOOL prompts you for some data sites and data values to fit and
%   lets you do this in various ways.
%   One of the choices is to provide your own data, in which case both
%   the sites and values can be expressions that evaluate to vectors required 
%   to be of the same length.
%   You can also specify the values by providing the name of a function whose 
%   values at the sites are to be used as data values.
%   You can also provide the name of an M-file (like 'titanium') whose 
%   two-argument output provides numerical values for sites and values.
%   In any case, there must be at least two distinct sites.
%   The other choices provide specific sample sites and values to illustrate 
%   various aspects of the GUI.
%
%   SPLINETOOL(X,Y) uses the input data sites X and data values Y, and these
%   must be numerical vectors of the same length > 1. The data sites need not
%   be distinct nor ordered, but there must be at least two distinct sites.
%
%   Example:
%      x = linspace(1,pi,101); y = cos(x)+(rand(size(x))-.5)/10;
%      splinetool(x,y)
%   might start an interesting experimentation with noisy data.
%
%   See also CSAPI, CSAPS, SPAPS, SPAP2, SPAPI.

%   Copyright 1987-2005 C. de Boor and The MathWorks, Inc.
%   $Revision: 1.38.4.2 $  $Date: 2005/05/31 16:41:11 $

updated = '04may05'; testing = 0;
v = ver('splines'); if size(v,2)>1, v = v(:,1); end
[relYear,ignored] = datevec(v.Date);
abouttext = {[v.Name ' ' v.Version]; ...
             ['Copyright 1987-' int2str(relYear) ' C. de Boor and The MathWorks, Inc.']};

if nargin<1  % import data

   action = 'start';

else
   if ischar(x)
      action = x;  hand = get(gcbf,'Userdata');
      if isstruct(hand)&&isfield(hand,'currentline')
         hc = hand.currentline; % make available, for use with changes
      end

   else % check and sort the given data
      [x,y] = chckxy(x,y);
      xname = 'x'; yname = 'y';
      isf = 0;
      action = 'start';
   end
end

switch action

case 'add_item'    % add an item

   switch get(hand.data_etc,'Value')
   case 1
      [xx,yy] = ask_for_add(hand);
      x = get(hand.dataline,'Xdata');
      if xx<x(1)||xx>x(end)
         warndlg(['The Spline Tool will let you only', ...
	           ' add interior data sites.'], ...
             'Attempted change of interval of approximation','modal')
      elseif get(hand.method,'Value')==4&&~isempty(find(x==xx,1))
         warndlg(['Since SPAPI would interpret repeated data sites',...
          ' as a request for osculatory interpolation, the Spline Tool',...
	  ' won''t let you create repeated data sites now.'], ...
	  'Repeated data sites', 'modal');
      else
         set(hand.undo,'Enable','on')
         insert_and_mark(x,get(hand.dataline,'Ydata'),xx,yy,hand)
         undoud = get(hand.undo,'Userdata');
         undoud.lineud = get(hand.nameline,'Userdata');
         set(hand.undo,'Userdata',undoud);

         get_approx(hand)
      end
      if isequal(get(hand.undo,'Enable'),'off')
         V = get(hand.params(1,3),'Value');
         set(hand.params(2,3),'String',x(V))
         if isequal(get(hand.params(2,5),'Visible'),'on')
            y = get(hand.dataline,'Ydata');
            set(hand.params(2,5),'String',y(V))
         end
      end

   case 2
      switch get(hand.method,'Value')
      case 3
         xx = ask_for_add(hand);
         lineud = get(hand.nameline,'Userdata');
         [lineud.knots,i] = sort([lineud.knots,xx]);
         placed = find(i==length(lineud.knots));
         if placed==1||placed==length(lineud.knots)
            warndlg('The Spline Tool will only let you add interior knots.',...
                'The end knots are forever','modal')
            lineud.knots(placed)=[];
            set(hand.nameline,'Userdata',lineud)
            set(hand.params(2,4),'String', ...
            lineud.knots(get(hand.params(1,4),'Value')))

         else
            set(hand.params(1,4),'String',lineud.knots(:),'Value', placed)
            lineud = update(hand,'knots',lineud);
            lineud.kc(end+1) = ...
                  addchange(hc,['knots = sort([knots,',num2str(xx,15),']);',...
                  ' %% you added a knot']);
            set(hand.nameline,'Userdata',lineud)
            % update knots display
	    set(hand.buttonm,'Visible','on')
            markb(hand), set_bdisplay(lineud.knots,hand)

            get_approx(hand)
         end
      end %switch get(hand.method,'Value')
   case 3

   end %switch get(hand.data_etc,'Value')

case 'align'  % make sure the left and right data list are aligned
   % at present, this serves no function, but sits here in case clicking 
   % anywhere on a list box activates a callback
   tag = get(gcbo,'Tag');
   if tag(5)=='l', j=3; else j=5; end
   set(hand.params(1,8-j),'Value',get(hand.params(1,j),'Value'))

case 'axesclick'  % action when the axes is clicked

   % protect against clicks on Print Figure window:
   if isempty(hand), return, end
   % only react here to LEFT clicks
   tmp = get(hand.figure,'SelectionType');
   if tmp(1)=='n'

      % get the location of the latest click in data coordinates:
      clickp = get(hand.Axes(1),'CurrentPoint');

      switch get(hand.data_etc,'Value')
      case {1,3} % highlight the nearest data point
         highlightn(clickp,hand)

      case 2
         switch get(hand.method,'Value')
         case {1,3,4}

            % find the nearest break
            breaks = str2num(get(hand.params(1,4),'String'));
            [ignored,V]=min(abs(breaks(:)-repmat(clickp(1),length(breaks),1)));
            if get(hand.params(1,4),'Value')~=V
               set(hand.params(1,4),'Value',V), markb(hand)
            end
         case 2
            highlightn(clickp,hand)

         end %switch get(hand.method,'Value')

      end %switch get(hand.data_etc,'Value')
   end %if tmp(1)=='n'

case 'change_name' % change the name of the current spline

   names = get_names(get(hand.list_names,'String'));
   V = get(hand.list_names,'Value');
   oldname = names(V,:);  oldname = oldname(6:end);
   name = '';
   while isempty(name)
      answer = inputdlg(...
        'Give a (valid MATLAB variable) name for the current spline:',...
        'Please provide a new name for the current spline ...', 1,...
        {deblank(oldname)});
      if isempty(answer)||strcmp(answer{:},oldname), return, end
      name = full_name(answer{1});
   end
   hand.name = name; hand.dbname = deblank(name);
   set(hand.figure,'Userdata',hand)
   if get(hand.ask_show,'Value')==1
      names(V,:) = ['v || ',name];
   else
      names(V,:) = ['  || ',name];
   end
   set(hand.list_names,'String',{names})
   lineud = update(hand,'fit');
   if isfield(lineud,'kc')
      lineud.kc(end+1) = addchange(hc, ...
           [hand.dbname,' = ',deblank(oldname),'; %% you changed the name']);
   end
   lineud.bottom = [' ',hand.dbname, ...
                   lineud.bottom(findstr(' =',lineud.bottom(1:14)):end)];
   set(hand.bottomlinetext, 'String',lineud.bottom)
   set(hand.nameline,'Tag',name,'Userdata',lineud)
   set_view_label(name,hand)
   if names(V,1)=='v'
      legend(hand.Axes(1),'off'), set_legend(hand,hand.Axes(1))
   end

case 'change_order' % call_back from the order selector in approximation field

   M = get(hand.method,'Value');
   switch M

   case 2 % we are smoothing, hence now must change the edit fields
      set_edits(2,hand)

   case {3,4}
      lineud = update(hand,'knots');
      lineud.k = get(hand.order,'Value');
      if M==3  % we are doing least-squares
         lineud.knots = augknt(lineud.knots,lineud.k);
         lineud.kc(end+1) = ...
               addchange(hc,['knots = augknt(knots,',num2str(lineud.k),');',...
                  ' %% you changed the order']);
      else     % we are doing interpolation
         [lineud.knots,lineud.k] = aptknt(get(hand.dataline,'Xdata'),lineud.k);
      end
      if get(hand.data_etc,'Value')==2  %  need to update the knot display
         set(hand.params(1,4),'String',lineud.knots(:),'Value',1+lineud.k)
         markb(hand), set_bdisplay(lineud.knots,hand)
      end
      set(hand.nameline,'Userdata',lineud)

   end %switch M

   get_approx(hand)

case {'close','exit','finish','quit'} % terminate splinetool

   answer = questdlg(...
            sprintf(['Do you really want to quit the SPLINE TOOL?\n', ...
	             'All unsaved data or approximations will be lost.']), ...
                     'Do you want to quit?','OK','Cancel','OK');
   if isempty(answer)||answer(1)=='C', return, end
   splinetool 'closefile'

case 'closefile' % close splinetool without further ado

   delete(findobj('Tag','Spline Tool Example Message Box'))
   delete(findobj(allchild(0),'name','Spline Tool'))

case 'data_etc'  % callback from 'data_etc' to set up for present edit choice

   if nargin>1,  hand = y; end
   % start clean
   set([reshape(hand.params(:,3:5),15,1); hand.buttonm; hand.piecem; ...
        hand.piecetext; ...
        hand.highlightxy;hand.highlightb;hand.breaks(:);hand.rep_knot(:); ...
        hand.add_item(:);hand.del_item(:)], 'Visible','off')
   set(hand.breaks(:),'Userdata','off')
   set(hand.undo,'Enable','off')

   switch get(hand.data_etc,'Value')
   case 1  % turn on the data display
      set(hand.add_item,'Label','&Add Point ...','Visible','on')
      set(hand.del_item,'Label','&Delete Point','Visible','on')
      set(get(hand.Axes(1),'Children'),'UIContextMenu',hand.context)
      x = get(hand.dataline,'Xdata');
      set(hand.params(1,3),'String',x, ...
         'Visible','on', ...
         'Backgroundcolor',[1 1 1], ...
         'Callback','splinetool ''highlightxy''', ...
         'TooltipString', ...
        'Mark a point, for editing below (same as leftclick on point in graph)')
      set(hand.params(2,3),'String',x(1),'Visible','on')
      set(hand.params([3 5],3), 'Visible','on')
      set(hand.params(4,3),'Visible','on','Value',0)
      if ~get(hand.params(4,3),'Value')
        set(hand.params(4,3),'String',(x(end)-x(1))/(10*length(x)))
      end

      y = get(hand.dataline,'Ydata');
      if get(hand.dataline,'Userdata')
         set(hand.params(1,5),'String',y,'Visible','on', ...
            'Backgroundcolor',.9*[1 1 1], ...
            'Callback','splinetool ''highlightxy''', ...
            'TooltipString','')
      else
         set(hand.params(1,5),'String',y, 'Visible','on', ...
            'Backgroundcolor',[1 1 1], ...
            'Callback','splinetool ''highlightxy''', ...
            'TooltipString', ...
        'Mark a point, for editing below (same as leftclick on point in graph)')
         set(hand.params(2,5),'String',y(1),'Visible','on')
         set(hand.params([3 5],5), 'Visible','on')
         set(hand.params(4,5),'Visible','on','Value',0)
         if ~get(hand.params(4,5),'Value')
           set(hand.params(4,5),'String',(max(y)-min(y))/(10*length(y)))
         end
      end %if get(hand.dataline,'Userdata')
      set(hand.highlightxy,'Visible','on')
      markxy(hand) % also sets the editclkr field

   case 2
      M = get(hand.method,'Value');
      switch M
      case 1   % turn on the breaks display on the middle
         set(get(hand.Axes(1),'Children'),'UIContextMenu',[])
         lineud = get(hand.nameline,'Userdata');
         breaks = fnbrk(lineud.cs,'breaks');
         set(hand.params(1,4),'String',breaks(:), ...
         'Visible','on', ...
         'TooltipString','Mark a break', ...
         'Callback','splinetool ''highlightb''')
         set_bdisplay(breaks,hand), markb(hand)
         set(hand.highlightb,'Visible','on')

      case 2   % turn on the sites/weight display
         set(get(hand.Axes(1),'Children'),'UIContextMenu',[])
         set(hand.params(1,3),'String',get(hand.dataline,'Xdata'), ...
            'Visible','on', ...
            'Backgroundcolor',.9*[1 1 1], ...
            'Callback','splinetool ''highlightxy''', ...
            'TooltipString','')
         lineud = get(hand.nameline,'Userdata');
         set(hand.params(1,5),'String',lineud.w(:), ...

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?