image thumbnail

Waveform Generator GUI 2

by

 

22 Feb 2012 (Updated )

Generate waveformed signal and play it. Interactive GUI with movable datapoints.

interactive_curve
classdef interactive_curve < handle
     properties (SetAccess = public)
         figureHandle
         axesHandle
         numberOfMarkers
         x % makers x-coordinates
         y  % makers y-coordinates
         lineHandle
         xMargin % margin to prevent too close to border of axes, marker can not be closer to horizontal border then xMargine
         yMargin % margin to prevent too close to border of axes, marker can not be closer to verticle border then yMargine
         gap % margin to prevent too close markers, makere can not be closer then gap to another marker in x direction
         xLine % x coordinaties of the line, line x cordinates is xLine, y coordinatioes is interpolation(xLine)
         userFunctionHandle % user defined function for interpolation, used when method='userdefined'
         markersHandles % array of handles to markers
         MarkersInLine % if MarkersInLine=true then in line draw extend xLine with makers x coordinaties
         mouseMode % mouseMode=1 then mode of move makrers, mouseMode=2 then mode of add maker, mouseMode=3 then mode of reamove maker
         motionFunctionHandle % this function will be called contiusly while a marker move, it will be placed in redraw() and button_motion() method, if isempty(motionFunctionHandle)=true, then no function execution (default case)
         motionFunctionArgument % argument for motion function, one argument, for many arguments use cell array
         boundary % if boundary=0 then no boundary (default), if boundary=1 then set boundary to boundaryYLeft and boundaryYRight, if boundary=2 then periodic boundary
         boundaryYLeft % left boundary point y-value, used if ic.boundary=1
         boundaryYRight % right boundary point y-value, used if ic.boundary=1
         additionalDeleteFunctionHandle % handle to function that will be run additionaly when delete interactive_curve, defult is empty, this function has no input argument
     end
     properties (SetAccess = protected)
         method % interpolation method: 'nearest' 'linear' 'spline' 'pchip' 'cubic' 'v5cubic' 'delta' 'userdefined'
     end
     methods (Access = private)
         % mouse functions:
         function button_down(ic,src,eventdata)
             % used when mouse button clicked
             makerHandle=src;
             switch ic.mouseMode
                 case 1 % mode of maker motion
                    set(ic.figureHandle,'WindowButtonMotionFcn',{@ic.button_motion,makerHandle});
                 case 3 % mode of delete marker
                     ic.deleteMarkerByHandle(makerHandle);
             end
         end
         
         function button_motion(ic,src,eventdata,makerHandle)
            % used when mouse motion with mouse button clicked
            p=get(ic.axesHandle,'CurrentPoint');
            px=p(1,1);
            py=p(1,2);

            % axes limits:
            xx=get(ic.axesHandle,'XLim');
            yy=get(ic.axesHandle,'YLim');
            x1=xx(1)+ic.xMargin;
            x2=xx(2)-ic.xMargin;
            y1=yy(1)+ic.yMargin;
            y2=yy(2)-ic.yMargin;

            % limits from rest markers:
            f=find(ic.markersHandles==makerHandle); % find current maker in list of markers.
            L=length(ic.markersHandles);
            dx=x2-x1;
            %dxs=dx/(4*L); % margin, prevent too close markers
            dxs=ic.gap;
            switch L
                case 1
                    xx1=x1;
                    xx2=x2;
                case 2
                    if f==1
                        xx1=x1;
                        xx2=get(ic.markersHandles(2),'XData')-dxs;
                    else
                        % f==2
                        xx1=get(ic.markersHandles(1),'XData')+dxs;
                        xx2=x2;
                    end
                otherwise
                    switch f
                        case 1
                            xx1=x1;
                            xx2=get(ic.markersHandles(2),'XData')-dxs;
                        case L
                            xx1=get(ic.markersHandles(L-1),'XData')+dxs;
                            xx2=x2;
                        otherwise
                            xx1=get(ic.markersHandles(f-1),'XData')+dxs;
                            xx2=get(ic.markersHandles(f+1),'XData')-dxs;
                    end
            end

            if px<xx1
                px=xx1;
            end
            if px>xx2
                px=xx2;
            end
            if py<y1
                py=y1;
            end
            if py>y2
                py=y2;
            end



            % update markers:
            set(makerHandle,'XData',px,'YData',py);
            ic.x(f)=px;
            ic.y(f)=py;

            % update line:
            if ic.MarkersInLine
                xLineExtended=unique([ic.xLine ic.x]);
            else
                xLineExtended=ic.xLine;
            end
            yi=ic.interp1extended(ic.x,ic.y,xLineExtended,ic.method,ic.userFunctionHandle);
            set(ic.lineHandle,'XData',xLineExtended,'YData',yi);
            
            % motion function:
            if ~isempty(ic.motionFunctionHandle)
                mfn=ic.motionFunctionHandle;
                mfn(ic.motionFunctionArgument);
            end
            
            drawnow;
         end
         
         function button_up(ic,src,eventdata)
             % used when mouse button released
            figureHandle=src;
            set(figureHandle,'WindowButtonMotionFcn','');
         end
         
         function axes_button_down(ic,src,eventdata)
             % used when clicked in axes to create new makrer if ic.mouseMode=2
             if ic.mouseMode==2
                 p=get(ic.axesHandle,'CurrentPoint');
                 px=p(1,1);
                 py=p(1,2);
                 ic.addMarker(px,py,'auto');
             end
         end
         
         function close_figure_request(ic,src,eventdata)
             % used when figure close
             hf=ic.figureHandle;
             delete(ic); % delete interactive curve
             delete(hf); % delete figure
         end
     end
     methods
         function ic=interactive_curve(varargin)
             % creates intreractive curve
             % ic=interactive_curve creates new figure and axes and creats interactive curve there
             % ic=interactive_curve(figureHandle,axesHandle) creates intreractive curve in axes with handle axesHandle in fugure with handle figureHandle
             % ic=interactive_curve(figureHandle,axesHandle,markersX,markersY) with specified markers positions
             % ic=interactive_curve(figureHandle,axesHandle,markersX,markersY,XLim,YLim)  with specified markers positions and axes limits
             if nargin==0
                figureHandle=figure;
                axesHandle=axes;
                axis(axesHandle,'manual');
             else
                figureHandle=varargin{1};
                axesHandle=varargin{2};
             end
             ic.figureHandle=figureHandle;
             ic.axesHandle=axesHandle;
             ic.mouseMode=1;
             ic.motionFunctionHandle=[]; % no function
             ic.motionFunctionArgument=[]; % no arguments
             ic.additionalDeleteFunctionHandle=[]; % no function
             ic.boundary=0; % no boundary
             ic.boundaryYLeft=0;
             ic.boundaryYRight=0;
             %xMargin=0.15;
             %yMargin=0.05;
             %gap=0.15;
             
             
             
             set(figureHandle,'WindowButtonUpFcn',{@ic.button_up},...
                 'HitTest','off');
             ic.MarkersInLine=true;
             if nargin<=2
                 numberOfMarkers=10;
                 x=1:numberOfMarkers;
                 y=zeros(size(x));
             elseif nargin>=4
                 x=varargin{3};
                 y=varargin{4};
                 numberOfMarkers=length(x);
             end
             ic.x=x;
             ic.y=y; % makers coordinates
             xMargin=(max(x)-min(x))/70;
             yMargin=0.05;
             gap=(max(x)-min(x))/70;
             ic.xMargin=xMargin;
             ic.yMargin=yMargin;
             ic.gap=gap;
             markersHandles=zeros(1,numberOfMarkers);
             NextPlot=get(axesHandle,'NextPlot');
             set(axesHandle,'NextPlot','add',...
                 'HitTest','on');
             
             if nargin<=2
                set(axesHandle,'XLim',[min(x)-xMargin max(x)+xMargin],'YLim',[-1-yMargin 1+yMargin]);
             elseif nargin==4
                 set(axesHandle,'XLim',[min(x)-xMargin max(x)+xMargin],'YLim',[min(y)-yMargin max(y)+yMargin]);
             elseif nargin==6
                 set(axesHandle,'XLim',varargin{5},'YLim',varargin{6});
             end
             
             
             method='linear';
             %method='nearest';
             %method='delta';
             ic.method=method;
             lineResolution=100;
             %xi=linspace(x(1),x(end),lineResolution);
             xlm=get(axesHandle,'XLim');
             xi=linspace(xlm(1),xlm(2),lineResolution);
             xLine=xi;
             if ic.MarkersInLine
                xLineExtended=unique([xLine ic.x]);
             else
                xLineExtended=xLine;
             end
             %yi=interp1(x,y,xi,method);
             yi=ic.interp1extended(x,y,xLineExtended,method,[]);
             lineHandle=plot(xLineExtended,yi,'k-','HitTest','off','parent',axesHandle);
             for c=1:numberOfMarkers
                markersHandles(c)=plot(x(c),y(c),'ko','MarkerFaceColor','g','markersize',10,...
                    'parent',axesHandle,'HitTest','on');
             end
             
             ic.numberOfMarkers=numberOfMarkers;
             ic.markersHandles=markersHandles;
             ic.lineHandle=lineHandle;
             ic.xLine=xLine;
             ic.userFunctionHandle=[]; % empty
             for c=1:numberOfMarkers
                 set(markersHandles(c),'ButtonDownFc',{@ic.button_down});
             end
             
             ic.markersHandles=markersHandles;
             
             set(axesHandle,'NextPlot',NextPlot); % return back nextplot property
             
             set(axesHandle,'ButtonDownFcn',{@ic.axes_button_down});
             
             % to delete interactive_curve objecte befor close figure:
             set(figureHandle,'CloseRequestFcn',{@ic.close_figure_request});
             
             
         end
         function setMethod(ic,method)
             % ic.setMethod(method) set new method of interpolation
             % interp1 methods: 'nearest' 'linear' 'spline' 'pchip' 'cubic' 'v5cubic', see help for interp1
             % aditional method: 'delta' - each marker makes delta function
             % 'userdefined'  to define some other method, use userFunctionHandle property
             
             % check input:
             if any(strcmpi(method,{'nearest','linear','spline','pchip','cubic','v5cubic','delta','userdefined'}))
                 
             else
                 error(['unknown method: '  method]);
             end
             
             ic.method=method;
             ic.redraw();
         end
         function redraw(ic)
             % ic.redraw() update line
             if ic.MarkersInLine
                xLineExtended=unique([ic.xLine ic.x]);
             else
                xLineExtended=ic.xLine;
             end
             yi=ic.interp1extended(ic.x,ic.y,xLineExtended,ic.method,ic.userFunctionHandle);
             set(ic.lineHandle,'XData',xLineExtended,'YData',yi);
             if ~isempty(ic.motionFunctionHandle)
                mfn=ic.motionFunctionHandle;
                mfn(ic.motionFunctionArgument);
             end
             
             drawnow;
         end
         function setMarkersColor(ic,color)
             % ic.setMarkersColor(color) change markers face color, color symbol or 3-elements vector
             for mc=1:length(ic.markersHandles)
                 hm=ic.markersHandles(mc);
                 set(hm,'MarkerFaceColor',color);
             end
         end
         function setMarkersSize(ic,sz)
             % ic.setMarkersSize(sz) change markers size, units: points
             for mc=1:length(ic.markersHandles)
                 hm=ic.markersHandles(mc);
                 set(hm,'markersize',sz);
             end
         end
         function setMarkersSymbol(ic,sb)
             % ic.setMarkersSymbol(sb) set marker symbol, 'o'  'x' '+' ect, see help for plot
             for mc=1:length(ic.markersHandles)
                 hm=ic.markersHandles(mc);
                 set(hm,'Marker',sb);
             end
         end
         
         function deleteMarkerByNumber(ic,markerNumber)
             % ic.deleteMarkerByNumber(markerNumber)  delete marker by order number
             L=length(ic.markersHandles);
             if (1<=markerNumber)&&(markerNumber<=L)
                delete(ic.markersHandles(markerNumber));
                ind=find((1:L)~=markerNumber);
                ic.markersHandles=ic.markersHandles(ind);
                ic.numberOfMarkers=length(ic.markersHandles);
                ic.x=ic.x(ind);
                ic.y=ic.y(ind);
                ic.redraw();
             end
         end
         
         function deleteMarkerByHandle(ic,makerHandle)
             % ic.deleteMarkerByHandle(makerHandle)  delete marker by marker handle
             L=length(ic.markersHandles);
             markerNumber=find(ic.markersHandles==makerHandle);
             if ~isempty(markerNumber)
                delete(ic.markersHandles(markerNumber));
                ind=find((1:L)~=markerNumber);
                ic.markersHandles=ic.markersHandles(ind);
                ic.numberOfMarkers=length(ic.markersHandles);
                ic.x=ic.x(ind);
                ic.y=ic.y(ind);
                ic.redraw();
             end
         end
         
         function addMarker(ic,markerX,markerY,varargin)
             % add marker to specified position
             % ic.addMarker(markerX,markerY) - add marker, do not change xLine
             % ic.addMarker(markerX,markerY,xLineNew) - add marker and change xLine to xLineNew
             % ic.addMarker(markerX,markerY,'auto') - add marker and auto extend xLine if neccesary
             L=length(ic.markersHandles);
             NextPlot=get(ic.axesHandle,'NextPlot');
             set(ic.axesHandle,'NextPlot','add');
             if L==0
                markersHandle=plot(markerX,markerY,'ko','MarkerFaceColor','g','markersize',10,...
                        'parent',ic.axesHandle,'HitTest','on');
             else
                 h=ic.markersHandles(1);
                 c=get(h,'MarkerFaceColor');
                 m=get(h,'Marker');
                 ms=get(h,'markersize');
                 ec=get(h,'MarkerEdgeColor');
                 ls=get(h,'LineStyle');
                 cl=get(h,'Color');
                 markersHandle=plot(markerX,markerY,'MarkerFaceColor',c,'markersize',ms,'MarkerEdgeColor',ec,...
                     'LineStyle',ls,'marker',m,'Color',cl,...
                        'parent',ic.axesHandle,'HitTest','on');
             end
             set(markersHandle,'ButtonDownFc',{@ic.button_down});
             
             
             ff=find(ic.x<markerX);
             if isempty(ff)
                 % new marker is righter then all old markers
                 ic.markersHandles=[markersHandle ic.markersHandles];
                 ic.numberOfMarkers=length(ic.markersHandles);
                 ic.x=[markerX ic.x];
                 ic.y=[markerY ic.y];
             else
                fm=max(ff); % most right marker that on left side of new marker
                ic.markersHandles=[ic.markersHandles(1:fm) markersHandle ic.markersHandles(fm+1:end)];
                ic.numberOfMarkers=length(ic.markersHandles);
                ic.x=[ic.x(1:fm) markerX ic.x(fm+1:end)];
                ic.y=[ic.y(1:fm) markerY ic.y(fm+1:end)];
             end
             set(ic.axesHandle,'NextPlot',NextPlot); % return back nextplot property
             
             % extend limits if need:
             %set(ic.axesHandle,'XLim',[min(ic.x)-ic.xMargin max(ic.x)+ic.xMargin],'Ylim',[min(ic.y)-ic.yMargin max(ic.y)+ic.yMargin]);
             xl=get(ic.axesHandle,'XLim');
             if (min(ic.x)<xl(1))||(xl(2)<max(ic.x))
                set(ic.axesHandle,'XLim',[min(ic.x)-ic.xMargin max(ic.x)+ic.xMargin]);
             end
             yl=get(ic.axesHandle,'YLim');
             if (min(ic.y)<yl(1))||(yl(2)<max(ic.y))
                set(ic.axesHandle,'Ylim',[min(ic.y)-ic.yMargin max(ic.y)+ic.yMargin]);
             end
             
             if nargin>3
                 if ~ischar(varargin{1})
                     % addMarker(ic,markerX,markerY,xLineNew) - add marker and change xLine to xLineNew
         
                     ic.xLine=varargin{1};
                 else
                     if strcmpi(varargin{1},'auto')
                         % addMarker(ic,markerX,markerY,'auto') - add marker and auto extend xLine if neccesary
                         % extend xLine if need:
                         %if (xMarker<ic.xLine(1))||(xMarker>ic.xLine(end))
                         if (markerX<ic.xLine(1))
                            % update xLine:
                            dx=mean(diff(ic.xLine)); % define step as mean
                            extn=ic.xLine(1):-dx:markerX; % example: extn=[1 0.8 0.6] (markerX=0.5, dx=0.2, xLine(1)=1)
                            fextn=fliplr(extn); %=[0.6 0.8 1]
                            ic.xLine=[fextn(1:end-1) ic.xLine];
                           
                         end
                         if (markerX>ic.xLine(end))
                            % update xLine:
                            dx=mean(diff(ic.xLine)); % define step as mean
                            extn=ic.xLine(end):dx:markerX;
                            ic.xLine=[ic.xLine extn(2:end)];
                         end
                     end
                 end
             end

            ic.redraw();
             
         end
         
         function setMarkersInLine(ic,tf)
            % ic.setMarkersInLine(tf)  set MarkersInLine property and redraw line
            % if MarkersInLine=true then in line draw extend xLine with makers x coordinaties
            ic.MarkersInLine=tf;
            ic.redraw();
         end
         
         
         function yi=interp1extended(ic,x,y,xi,method,userFunctionHandle)
             % ic.interp1extended(x,y,xi,method,userFunctionHandle)  makes interpolation
             % used in redraw line and in interpData()
             if (length(x)<2)&&(ic.boundary~=1)
                 yi=NaN(size(xi));
             else
             
                if strcmpi(method,'userdefined')
                    if ic.boundary==0
                        yi=userFunctionHandle(x,y,xi);
                    elseif ic.boundary==1 % user defined boundaryYLeft and boundaryYRight
                        xlm=get(ic.axesHandle,'XLim'); 
                        yi=userFunctionHandle([xlm(1) x xlm(2)],[ic.boundaryYLeft y ic.boundaryYRight],xi);
                    elseif ic.boundary==2 % periodic boundary
                        xlm=get(ic.axesHandle,'XLim');
                        T=xlm(2)-xlm(1);
                        x5=[x-2*T  x-T  x  x+T  x+2*T];
                        yi=userFunctionHandle(x5,[y y y y y],xi);
                    end
                    return;
                end

                if strcmpi(method,'delta')
                    % in delta interpolation give same result indepedtently
                    % from boundary



                    ind=interp1(xi,1:length(xi),x,'nearest'); % index of xi, length(x)=length(ind)=number of markers
                    yi=zeros(size(xi));
                    yi(ind(~isnan(ind)))=y(~isnan(ind));
                    return;
                end

                % otherwise interp1:
                if ic.boundary==0
                    yi=interp1(x,y,xi,method);
                elseif ic.boundary==1 % user defined boundaryYLeft and boundaryYRight
                    xlm=get(ic.axesHandle,'XLim');
                    yi=interp1([xlm(1) x xlm(2)],[ic.boundaryYLeft y ic.boundaryYRight],xi,method); 
                elseif ic.boundary==2 % periodic boundary
                    xlm=get(ic.axesHandle,'XLim');
                    T=xlm(2)-xlm(1);
                    x5=[x-2*T  x-T  x  x+T  x+2*T];
                    yi=interp1(x5,[y y y y y],xi,method);
                end
             end
         end
         
         
         function yi=interpData(ic,xi,isXPeriodic)
             % ic.interpData(xi,isXPeriodic) interpolate specified data with current method and markers postion
             % if isXPeriodic=true then xi can be out of x axis limits and
             % will be move to x limits as periodic function before
             % interpolation
             xlm=get(ic.axesHandle,'XLim');
             T=xlm(2)-xlm(1);
             if strcmpi(ic.method,'delta')&&isXPeriodic
                mn=min(xi);
                mx=max(xi);
                Nmn=floor(mn/T);
                Nmx=floor(mx/T);
                N=Nmn:Nmx; % periods numbers
                n=Nmx-Nmn+1;
                xea=bsxfun(@plus,repmat(ic.x',1,n),T*N);
                xe=(xea(:))';
                ye=repmat(ic.y,1,n);
                yi=interp1extended(ic,xe,ye,xi,ic.method,ic.userFunctionHandle); 
             else
                if isXPeriodic
                    xi=mod(xi-xlm(1),T);
                end
                yi=interp1extended(ic,ic.x,ic.y,xi,ic.method,ic.userFunctionHandle);
             end
         end
         
         function setXLim(ic,XLim)
             % ic.setXLim(XLim) set new x limits in axes, XLim=[x_min  x_max]
             set(ic.axesHandle,'XLim',XLim);
         end
         
         function setYLim(ic,YLim)
             % ic.setYLim(YLim) set new y limits in axes, YLim=[y_min  y_max]
             set(ic.axesHandle,'YLim',YLim);
         end
         
         function setBoundary(ic,boundary)
             % ic.setBoundary(ic,boundary) 
             % if boundary=0 then no boundary (default)
             % if boundary=1 then set boundary to boundaryYLeft and boundaryYRight, if boundary=2 then periodic boundary
             ic.boundary=boundary;
             ic.redraw();
         end
         
         function MCode=generateMCode(ic,functionName,isXPeriodic)
             % MCode=ic.generateMCode(functionName,isXPeriodic) generates m-code for current settings for interpolation function
             % MCode is the text of the code as cell array of strings
             % if isXPeriodic=true then interpolation point xi fill be
             % shifted to x-axis limits as periodic function
             
%              xlm=get(ic.axesHandle,'XLim');
%              T=xlm(2)-xlm(1);
%              if strcmpi(ic.method,'delta')&&isXPeriodic
%                 mn=min(xi);
%                 mx=max(xi);
%                 Nmn=floor(mn/T);
%                 Nmx=floor(mx/T);
%                 N=Nmn:Nmx; % periods numbers
%                 n=Nmx-Nmn+1;
%                 xea=bsxfun(@plus,repmat(ic.x',1,n),T*N);
%                 xe=(xea(:))';
%                 ye=repmat(ic.y,1,n);
%                 yi=interp1extended(ic,xe,ye,xi,ic.method,ic.userFunctionHandle); 
%              else
%                 if isXPeriodic
%                     xi=mod(xi-xlm(1),T);
%                 end
%                 yi=interp1extended(ic,ic.x,ic.y,xi,ic.method,ic.userFunctionHandle);
%              end
             
             
             MCode=cell(0,1);
             MCode1=['function yi=' functionName '(xi)'];
             MCode=vertcat(MCode,MCode1);
             MCode1=['% autogenerated interpolation function ' datestr(now)];
             MCode=vertcat(MCode,MCode1);
             MCode1=['% by interactive_curve object'];
             MCode=vertcat(MCode,MCode1);
             if isXPeriodic&&(~strcmpi(ic.method,'delta'))
                 xlm=get(ic.axesHandle,'XLim');
                 T=xlm(2)-xlm(1);
                 MCode1=['xi=mod(xi-(' num2str(xlm(1),'%10.7e') '),' num2str(T,'%10.7e') ');'];
                 MCode=vertcat(MCode,MCode1);
             end
             
             if length(ic.x)<2
                 % yi=NaN(size(xi));
                 MCode1=['yi=NaN(size(xi));'];
                 MCode=vertcat(MCode,MCode1);
             else
                 if strcmpi(ic.method,'userdefined')
                     if ic.boundary==0
                         %yi=userFunctionHandle(x,y,xi);
                         MCode1=['x=[' num2str(ic.x,'%10.7e ') '];'];
                         MCode=vertcat(MCode,MCode1);
                         MCode1=['y=[' num2str(ic.y,'%10.7e ') '];'];
                         MCode=vertcat(MCode,MCode1);
                         
                         fst=func2str(ic.userFunctionHandle); % to string
                         % example:
                         % fst='@(x,y,xi)(0.8*interp1(x,y,xi,'nearest')+0.2*interp1(x,y,xi,'spline'))'
                         if fst(1)=='@'
                             % anonymouse function
                             MCode1=['userFunctionHandle=' fst ';'];
                             MCode=vertcat(MCode,MCode1);
                             MCode1=['yi=userFunctionHandle(x,y,xi);']; 
                             MCode=vertcat(MCode,MCode1);
                         else
                             % link to real function
                             % example:
                             % fst='my_interp' and there are my_interp.m file
                             MCode1=['yi=' fst '(x,y,xi);']; 
                             MCode=vertcat(MCode,MCode1);
                         end
                     elseif ic.boundary==1 % zero boundary
                         %xlm=get(ic.axesHandle,'XLim'); 
                         %yi=userFunctionHandle([xlm(1) x xlm(2)],[ic.boundaryYLeft y ic.boundaryYRight],xi);
                         
                         xlm=get(ic.axesHandle,'XLim');
                         MCode1=['x=[' num2str(xlm(1),'%10.7e ') ' ' num2str(ic.x,'%10.7e ') ' ' num2str(xlm(2),'%10.7e ') '];'];
                         MCode=vertcat(MCode,MCode1);
                         MCode1=['y=[' num2str(ic.boundaryYLeft,'%10.7e ') ' ' num2str(ic.y,'%10.7e ') ' ' num2str(ic.boundaryYRight,'%10.7e ') '];'];
                         MCode=vertcat(MCode,MCode1);
                         fst=func2str(ic.userFunctionHandle); % to string
                         if fst(1)=='@'
                             % anonymouse function
                             MCode1=['userFunctionHandle=' fst ';'];
                             MCode=vertcat(MCode,MCode1);
                             MCode1=['yi=userFunctionHandle(x,y,xi);']; 
                             MCode=vertcat(MCode,MCode1);
                         else
                             % link to real function
                             MCode1=['yi=' fst '(x,y,xi);']; 
                             MCode=vertcat(MCode,MCode1);
                         end
                     elseif ic.boundary==2 % periodic boundary
                         %xlm=get(ic.axesHandle,'XLim');
                         %T=xlm(2)-xlm(1);
                         %x5=[x-2*T  x-T  x  x+T  x+2*T];
                         %yi=userFunctionHandle(x5,[y y y y y],xi);
                         
                         xlm=get(ic.axesHandle,'XLim');
                         T=xlm(2)-xlm(1);
                         %x5=[x-2*T  x-T  x  x+T  x+2*T];
                         %yi=interp1(x5,[y y y y y],xi,method);
                         MCode1=['x=[' num2str(ic.x,'%10.7e ') '];'];
                         MCode=vertcat(MCode,MCode1);
                         MCode1=['y=[' num2str(ic.y,'%10.7e ') '];'];
                         MCode=vertcat(MCode,MCode1);
                         MCode1=['x5=[' num2str(ic.x-2*T,'%10.7e ') ' ' num2str(ic.x-T,'%10.7e ') ' ' num2str(ic.x,'%10.7e ') ' ' num2str(ic.x+T,'%10.7e ') ' ' num2str(ic.x+2*T,'%10.7e ') '];'];
                         MCode=vertcat(MCode,MCode1);
                         %MCode1=['yi=interp1(x5,[y y y y y],xi,''' ic.method ''');']; 
                         %MCode=vertcat(MCode,MCode1);
                         fst=func2str(ic.userFunctionHandle); % to string
                         if fst(1)=='@'
                             % anonymouse function
                             MCode1=['userFunctionHandle=' fst ';'];
                             MCode=vertcat(MCode,MCode1);
                             MCode1=['yi=userFunctionHandle(x5,[y y y y y],xi);']; 
                             MCode=vertcat(MCode,MCode1);
                         else
                             % link to real function
                             MCode1=['yi=' fst '(x5,[y y y y y],xi);']; 
                             MCode=vertcat(MCode,MCode1);
                         end
                     end
                     return;
                 end
                 
                if strcmpi(ic.method,'delta')
                    if isXPeriodic
                        % special case: periodic and delta
                        %                 mn=min(xi);
                        %                 mx=max(xi);
                        %                 Nmn=floor(mn/T);
                        %                 Nmx=floor(mx/T);
                        %                 N=Nmn:Nmx; % periods numbers
                        %                 n=Nmx-Nmn+1;
                        %                 xea=bsxfun(@plus,repmat(ic.x',1,n),T*N);
                        %                 xe=(xea(:))';
                        %                 ye=repmat(ic.y,1,n);
                        %                 yi=interp1extended(ic,xe,ye,xi,ic.method,ic.userFunctionHandle);
                        
                        MCode1=['x=[' num2str(ic.x,'%10.7e ') '];'];
                        MCode=vertcat(MCode,MCode1);

                        MCode1=['y=[' num2str(ic.y,'%10.7e ') '];'];
                        MCode=vertcat(MCode,MCode1);
                        
                        xlm=get(ic.axesHandle,'XLim');
                        T=xlm(2)-xlm(1);
                        MCode1=['T=' num2str(T,'%10.10e ') ';'];
                        MCode=vertcat(MCode,MCode1);
                        MCode1=['mn=min(xi);'];
                        MCode=vertcat(MCode,MCode1);
                        MCode1=['mx=max(xi);'];
                        MCode=vertcat(MCode,MCode1);
                        MCode1=['Nmn=floor(mn/T);'];
                        MCode=vertcat(MCode,MCode1);
                        MCode1=['Nmx=floor(mx/T);'];
                        MCode=vertcat(MCode,MCode1);
                        MCode1=['N=Nmn:Nmx; % periods numbers'];
                        MCode=vertcat(MCode,MCode1);
                        MCode1=['n=Nmx-Nmn+1;'];
                        MCode=vertcat(MCode,MCode1);
                        MCode1=['xea=bsxfun(@plus,repmat(x'',1,n),T*N);'];
                        MCode=vertcat(MCode,MCode1);
                        MCode1=['xe=(xea(:))'';'];
                        MCode=vertcat(MCode,MCode1);
                        MCode1=['ye=repmat(y,1,n);'];
                        MCode=vertcat(MCode,MCode1);
                        
                        MCode1=['ind=interp1(xi,1:length(xi),xe,''nearest'');'];
                        MCode=vertcat(MCode,MCode1);
                        %yi=zeros(size(xi));
                        MCode1=['yi=zeros(size(xi));'];
                        MCode=vertcat(MCode,MCode1);
                        %yi(ind(~isnan(ind)))=y(~isnan(ind));
                        MCode1=['yi(ind(~isnan(ind)))=ye(~isnan(ind));'];
                        MCode=vertcat(MCode,MCode1);
                        return;
                        
                    else
                        % in delta interpolation give same result indepedtently
                        % from boundary


                        MCode1=['x=[' num2str(ic.x,'%10.7e ') '];'];
                        MCode=vertcat(MCode,MCode1);

                        MCode1=['y=[' num2str(ic.y,'%10.7e ') '];'];
                        MCode=vertcat(MCode,MCode1);

                        %ind=interp1(xi,1:length(xi),x,'nearest'); % index of xi, length(x)=length(ind)=number of markers
                        MCode1=['ind=interp1(xi,1:length(xi),x,''nearest'');'];
                        MCode=vertcat(MCode,MCode1);
                        %yi=zeros(size(xi));
                        MCode1=['yi=zeros(size(xi));'];
                        MCode=vertcat(MCode,MCode1);
                        %yi(ind(~isnan(ind)))=y(~isnan(ind));
                        MCode1=['yi(ind(~isnan(ind)))=y(~isnan(ind));'];
                        MCode=vertcat(MCode,MCode1);
                        return;
                    end
                end

                % otherwise interp1:
                if ic.boundary==0
                    %yi=interp1(x,y,xi,method);
                    MCode1=['x=[' num2str(ic.x,'%10.7e ') '];'];
                    MCode=vertcat(MCode,MCode1);
                    MCode1=['y=[' num2str(ic.y,'%10.7e ') '];'];
                    MCode=vertcat(MCode,MCode1);
                    MCode1=['yi=interp1(x,y,xi,''' ic.method ''');']; 
                    MCode=vertcat(MCode,MCode1);
                elseif ic.boundary==1 % zero boundary
                    xlm=get(ic.axesHandle,'XLim');
                    %yi=interp1([xlm(1) x xlm(2)],[ic.boundaryYLeft y ic.boundaryYRight],xi,method); 
                    MCode1=['x=[' num2str(xlm(1),'%10.7e ') ' ' num2str(ic.x,'%10.7e ') ' ' num2str(xlm(2),'%10.7e ') '];'];
                    MCode=vertcat(MCode,MCode1);
                    MCode1=['y=[' num2str(ic.boundaryYLeft,'%10.7e ') ' ' num2str(ic.y,'%10.7e ') ' ' num2str(ic.boundaryYRight,'%10.7e ') '];'];
                    MCode=vertcat(MCode,MCode1);
                    MCode1=['yi=interp1(x,y,xi,''' ic.method ''');']; 
                    MCode=vertcat(MCode,MCode1);
                elseif ic.boundary==2 % periodic boundary
                    xlm=get(ic.axesHandle,'XLim');
                    T=xlm(2)-xlm(1);
                    %x5=[x-2*T  x-T  x  x+T  x+2*T];
                    %yi=interp1(x5,[y y y y y],xi,method);
                    MCode1=['x=[' num2str(ic.x,'%10.7e ') '];'];
                    MCode=vertcat(MCode,MCode1);
                    MCode1=['y=[' num2str(ic.y,'%10.7e ') '];'];
                    MCode=vertcat(MCode,MCode1);
                    MCode1=['x5=[' num2str(ic.x-2*T,'%10.7e ') ' ' num2str(ic.x-T,'%10.7e ') ' ' num2str(ic.x,'%10.7e ') ' ' num2str(ic.x+T,'%10.7e ') ' ' num2str(ic.x+2*T,'%10.7e ') '];'];
                    MCode=vertcat(MCode,MCode1);
                    MCode1=['yi=interp1(x5,[y y y y y],xi,''' ic.method ''');']; 
                    MCode=vertcat(MCode,MCode1);
                end
             end
         end
         
         function generateMFile(ic,filename,isXPeriodic)
             % MCode=ic.generateMFile(filename,isXPeriodic) generates m-file for current settings for interpolation function
             % if isXPeriodic=true then interpolation point xi fill be
             % shifted to x-axis limits as periodic function
             [pathstr, name, ext] = fileparts(filename);
             MCode=ic.generateMCode(name,isXPeriodic);
             fid = fopen(filename, 'w');
             for c=1:length(MCode)
                 fprintf(fid, '%s\n', MCode{c});
             end
             fclose(fid);
         end
         
         
         function setMarkersPositions(ic,markersX,markersY)
             % ic.setMarkersPositions(markersX,markersY)
             % set new positions for markers
             % if length(ic.markersHandles)~=length(markersX) then number
             % of markers will be changed
             
             NextPlot=get(ic.axesHandle,'NextPlot');
             set(ic.axesHandle,'NextPlot','add');
             
             if length(ic.markersHandles)==length(markersX)
                 % same number of markers
                 for mc=1:length(ic.markersHandles)
                     set(ic.markersHandles(mc),'XData',markersX(mc),'YData',markersY(mc));
                 end
                 ic.x=markersX;
                 ic.y=markersY;
             else
                 % different
                 
                 L0=length(ic.markersHandles);
                 
                 % plot new markers:
                 L=length(markersX);
                 
                     
                 
                 if L0==0
                      ic.markersHandles=zeros(1,L);
                      % plot new:
                      for mc=1:L
                        ic.markersHandles(mc)=plot(markersX(mc),markersY(mc),'ko','MarkerFaceColor','g','markersize',10,...
                            'parent',ic.axesHandle,'HitTest','on');
                        set(ic.markersHandles(mc),'ButtonDownFc',{@ic.button_down});
                      end
                 else
                     h=ic.markersHandles(1);
                     c=get(h,'MarkerFaceColor');
                     m=get(h,'Marker');
                     ms=get(h,'markersize');
                     ec=get(h,'MarkerEdgeColor');
                     ls=get(h,'LineStyle');
                     cl=get(h,'Color');
                     % delete all graphic markers from axes:
                     for mc=1:L0
                         delete(ic.markersHandles(mc));
                     end
                     ic.markersHandles=zeros(1,L);
                     % plot new:
                     for mc=1:L
                         
                         ic.markersHandles(mc)=plot(markersX(mc),markersY(mc),'MarkerFaceColor',c,'markersize',ms,'MarkerEdgeColor',ec,...
                             'LineStyle',ls,'marker',m,'Color',cl,...
                                'parent',ic.axesHandle,'HitTest','on');
                         set(ic.markersHandles(mc),'ButtonDownFc',{@ic.button_down});
                     end
                 end
                 
                 ic.x=markersX;
                 ic.y=markersY;
                 ic.numberOfMarkers=length(ic.markersHandles);
                 
             end
             set(ic.axesHandle,'NextPlot',NextPlot);
             ic.redraw();
         end
         
         
         
         
         
         
         
         
         
         
         
         
         function delete(ic)
             % ic.delete() delete interactive curve
             % delete interactive curve object makrers and line and empty callbacks in axes and figure
             
             % first run additionalDeleteFunctionHandle if exist:
             if ~isempty(ic.additionalDeleteFunctionHandle)
                 af=ic.additionalDeleteFunctionHandle;
                 af();
             end
             set(ic.figureHandle,'WindowButtonMotionFcn','','WindowButtonUpFcn','');
             set(ic.axesHandle,'ButtonDownFcn','');
             % delete instance of class
             for c=1:length(ic.markersHandles)
                 delete(ic.markersHandles(c));
             end
             delete(ic.lineHandle);
         end
         
         
         
         
     end
end

Contact us