function [n,a]=getslope(varargin)
%GETSLOPE  Slope of the current line.
%   GETSLOPE displays the equation of the current line of the figure. Use
%   the menu 'Insert > Line' to draw a line first. GETSLOPE allows for
%   rough curve fitting "by eye". You may also use the shortcut Ctrl+G if
%   the Ezyfit menu has been installed (see EFMENU).
%
%   Depending of the axis types, the equation of the line will be:
%        Y = N*X+A         for X linear and Y linear
%        Y = A*X^N         for X log and Y log
%        Y = A*EXP(N*X)    for X linear and Y log
%        Y = A+N*LOG(X)    for X log and Y linear (LOG = natural logarithm)
%
%   GETSLOPE('Property1',...) specifies the display mode:
%        'figure'   output the result in the figure (by default)
%        'command'  output the result in the command window
%        'nodisplay'  no output
%        'slope'    displays only the slope N (by default).
%        'equation' displays the full equation (e.g., N*X+A)
%
%   [N, A] = GETSLOPE(...) also returns the parameters N and A of the
%   equation.
%
%   See also SHOWSLOPE, PLOTSAMPLE, RMFIT, EFMENU.


%   F. Moisy, moisy_at_fast.u-psud.fr
%   Revision: 1.40,  Date: 2007/09/14
%   This function is part of the EzyFit Toolbox


% History:
% 2005/02/17: First version.
% 2005/02/23: uses the current active line
% 2005/02/24: bug 'nodisp' fixed
% 2005/05/21: standard error messages
% 2005/05/24: option 'draw' suppressed; works in linear or log coordinates.
% 2005/05/26: Bug fixed (zero slope in semilogx mode)
% 2005/06/16: Displays the fit parameters with the correct number of digits.
% 2005/06/22: v1.23, bug fixed in semilogx mode; 3 digits.
% 2005/07/27: v1.24, correctly displays the negative values (without '+').
% 2005/11/02: v1.30, works also when one extremity of the line is selected.
%                    the equation is now in an annotation box, that follows
%                    the line.
% 2006/02/08: v1.31, use the number of digits defined in fitparam
% 2006/03/08: v1.32, option 'dialog' added, when called from efmenu
% 2006/05/09: v1.33, bug fixed for exponential fits (annotation box too
%                    small)
% 2007/09/14: v1.40, the procedure for the detection of the line has been
%                    rewritten for ML 7.4-7.5; new options 'command' and
%                    'figure'


% loads the default fit parameters:
try
    fp=fitparam;
catch
    fp.numberofdigit=3;
end


if isempty(get(0,'CurrentFigure'))
    error('No figure.');
end

if isempty(legend)  % new v1.40
    islegend = false;
else
    islegend = true;
    legend off
end

strv=version;
v=str2double(strv(1:3));

if v>=7.4     % ------------------- FOR MATLAB 7.4 and 7.5
    % get infos about the current line
    if ~ishandle(gco)
        if any(strncmpi(varargin,'dialog',4))
            errordlg('First select a line (Menu Insert > Line)','GetSlope');
            return
        end
        error('First select a line (Menu Insert > Line).');
    end

    h=gco; % currently active line
    o=get(h);
    if ~isfield(o,'X')
        if any(strncmpi(varargin,'dialog',4))
            errordlg('First select a line (Menu Insert > Line)','GetSlope');
            return
        end
        error('First select a line (Menu Insert > Line).');
    end
    % this is the coord of the line, normalized to the window (between 0 and 1)
    xw1=o.X(1); xw2=o.X(2);
    yw1=o.Y(1); yw2=o.Y(2);

else   % ------------------- FOR MATLAB <=7.3
    % get infos about the current line
    if ishandle(gco),
        % gco is the currently active line (but it does not work
        % if the line has just being drawn!)
        if ~isfield(get(gco),'XData')
            % gco is a handle, but there is no XData field in it
            if (gco==gcf),
                % nothing is selected...
                if any(strncmpi(varargin,'dialog',4))
                    errordlg('First select a line (Menu Insert > Line)','GetSlope');
                    return;
                end
                error('First select a line (Menu Insert > Line).');
            else
                % this is the case when the line was just being drawn.
                % (h(1) is the XAxis, h(2) and h(3) are the first and second points,
                % and h(4) is the line itself).
                h=findall(gcf,'Type','line');
                if length(h)<4,
                    if any(strncmpi(varargin,'dialog',4))
                        errordlg('First select a line (Menu Insert > Line)','GetSlope');
                        return;
                    end
                    error('First select a line (Menu Insert > Line).');
                else
                    h=h(4);
                end
            end
        else
            % the object has a XData field in it
            h=gco;
            o=get(gco);
            if ~(length(o.XData)==2),
                if (length(o.XData)==1),
                    % One point of the line was being moved.
                    % go back to its parent and take the 3rd child:
                    % here you will find the line itself.
                    o=get(o.Parent);
                    h=o.Children(3);
                else
                    if any(strncmpi(varargin,'dialog',4))
                        errordlg('First select a line (Menu Insert > Line)','GetSlope');
                        return;
                    end
                    error('First select a line (Menu Insert > Line).');
                end
            end
        end
    else
        if any(strncmpi(varargin,'dialog',5))
            errordlg('First select a line (Menu Insert > Line)','GetSlope');
            return;
        end
        error('First select a line (Menu Insert > Line).');
    end
    o=get(h);
    % this is the coord of the line, normalized to the window (between 0 and 1)
    xw1=o.XData(1); xw2=o.XData(2);
    yw1=o.YData(1); yw2=o.YData(2);

end


icg=get(gca); % get infos about the current axes

% computes the coordinates of the line
% normalized to the axes of the figure (between 0 and 1):
%   icg.Position(1:2) = coordinates (x,y) relative to the window
%   icg.Position(3:4) = width and height of the windows
xr1=(xw1-icg.Position(1))/(icg.Position(3));
xr2=(xw2-icg.Position(1))/(icg.Position(3));


yr1=(yw1-icg.Position(2))/(icg.Position(4));
yr2=(yw2-icg.Position(2))/(icg.Position(4));

xb1=icg.XLim(1);
xb2=icg.XLim(2);
if strcmpi(icg.YDir, 'reverse')
    yb2=icg.YLim(1);  yb1=icg.YLim(2);
else
    yb1=icg.YLim(1);  yb2=icg.YLim(2);
end

if strncmpi(icg.XScale,'log',3) && strncmpi(icg.YScale,'log',3)
    % Fit by a power law, y=a*x^n.

    % computes the coordinates of the line in 'physical' units (those of
    % the axes):
    x1=xb1*(xb2/xb1)^xr1;
    x2=xb1*(xb2/xb1)^xr2;

    y1=yb1*(yb2/yb1)^yr1;
    y2=yb1*(yb2/yb1)^yr2;

    n=log(y2/y1)/log(x2/x1);
    a=y1/(x1^n);

    if any(strncmpi(varargin,'equation',2))
        str=[num2str(a, fp.numberofdigit) ' x^{' num2str(n, fp.numberofdigit) '}'];
    else
        str=num2str(n, fp.numberofdigit);
    end

elseif strncmpi(icg.XScale,'linear',3) && strncmpi(icg.YScale,'linear',3)
    % Fit by an affine law, y=nx+a.

    x1=xb1+(xb2-xb1)*xr1;
    x2=xb1+(xb2-xb1)*xr2;

    y1=yb1+(yb2-yb1)*yr1;
    y2=yb1+(yb2-yb1)*yr2;

    n=(y2-y1)/(x2-x1);
    a=y1-n*x1;

    if any(strncmpi(varargin,'equation',2))
        if a>0 % changed 27/07/2005, v1.24
            str=[num2str(n, fp.numberofdigit) ' x + ' num2str(a, fp.numberofdigit)];
        else
            str=[num2str(n, fp.numberofdigit) ' x ' num2str(a, fp.numberofdigit)];
        end
    else
        str=num2str(n, fp.numberofdigit);
    end

elseif strncmpi(icg.XScale,'linear',3) && strncmpi(icg.YScale,'log',3)
    % Fit by an exponential law, y=a*exp(nx).

    x1=xb1+(xb2-xb1)*xr1;
    x2=xb1+(xb2-xb1)*xr2;

    y1=yb1*(yb2/yb1)^yr1;
    y2=yb1*(yb2/yb1)^yr2;

    n=log(y2/y1)/(x2-x1);
    a=y1/exp(n*x1);

    if any(strncmpi(varargin,'equation',2))
        str=[num2str(a, fp.numberofdigit) ' e^{' num2str(n, fp.numberofdigit) ' x}'];
    else
        str=num2str(n, fp.numberofdigit);
    end

elseif strncmpi(icg.XScale,'log',3) && strncmpi(icg.YScale,'linear',3)
    % Fit by a logarithmic law, y=a+n*log(x).

    x1=xb1*(xb2/xb1)^xr1;
    x2=xb1*(xb2/xb1)^xr2;

    y1=yb1+(yb2-yb1)*yr1;
    y2=yb1+(yb2-yb1)*yr2;

    n=(y2-y1)/log(x2/x1);
    if n~=0
        a=y1-n*log(x1);
    else
        a=NaN;
    end
    if any(strncmpi(varargin,'equation',2))
        str=[num2str(a, fp.numberofdigit) ' ln (' num2str(n, fp.numberofdigit) ' x)'];
    else
        str=num2str(n, fp.numberofdigit);
    end
end


% if the current line has a textbox previously attached to it, kill it:
if ishandle(get(h,'UserData'))
    delete(get(h,'UserData'));
end

if ~any(strncmpi(varargin,'nodisplay',3))
    if any(strncmpi(varargin,'command',3))
        disp(str)
    end

    if (~any(strncmpi(varargin,'figure',3)) && ~any(strncmpi(varargin,'command',3))) ...
            || any(strncmpi(varargin,'figure',3))
        textlocation=[(xw1+xw2)/2 (yw1+yw2)/2-0.075-sign(n)*0.025 0.4 0.1];  % changed v1.33
        htext=annotation('textbox',textlocation,'LineStyle','none','UserData','getslopetextbox','String',str);
        % says to the line that the textbox htext is attached to it:
        set(h,'UserData',htext);
    end
end

if islegend
    legend show   % put back the legend (new v1.40)
end

if nargout==0
    clear n
end
