function [theResult, theIndex, x, y, z] = findpt(theLine, x, y, z)

% findpt -- Find the current point.
%  findpt(theLine) installs "findpt" in theLine (a handle) if called
%   directly, rather than as the result of a callback.  In this case,
%   theLine defaults to all the lines in the current figure.  During
%   mouse-down and mouse-move, the (x, y) location of the nearest
%   actual point on the original mouse-down line is displayed near
%   the mouse and in the figure-name.
%  [theLine, theIndex, x, y, z] = findpt(theLine, x, y, z) returns the
%   actual point on theLine [default = gcbo], that is nearest (x, y, z)
%   [default = present mouse position].  The returned values are packed
%   into a single vector if only one output argument is provided.  The
%   output (x, y, z) are the actual coordinates of the point.  If no
%   output arguments are given, the (x, y) result is displayed on the
%   plot and in the figure-name while the mouse is down.
 
% Copyright (C) 1997 Dr. Charles R. Denham, ZYDECO.
%  All Rights Reserved.
%   Disclosure without explicit written consent from the
%    copyright owner does not constitute publication.
 
% Version of 16-Sep-1997 09:44:49.

global theFigureName
global theFigureNumberTitle
global theLineHandle
global theTextHandle
global theMarkerHandle

DIGITS = 6;

if nargin < 1, theLine = gcbo; end

% If not a callback, install "findpt"
%  in all the lines in the figure.

if isempty(gcbo)
   if isempty(theLine)
      theLine = findobj(gcf, 'Type', 'line');
   end
   if any(theLine)
      set(theLine, 'ButtonDownFcn', 'findpt')
   end
   return
end

if nargin == 1
   switch theLine
   case 0   % Mouse up.
   if any(theTextHandle)
      delete(theTextHandle)
      delete(theMarkerHandle)
      set(gcf, 'Name', theFigureName, 'NumberTitle', theFigureNumberTitle)
      theLineHandle = [];
      theTextHandle = [];
      theMarkerHandle = [];
      set(gcf, 'Name', theFigureName, ...
               'NumberTitle', theFigureNumberTitle, ...
               'WindowButtonMotionFcn', '', ...
               'WindowButtonUpFcn', '')
      theFigureName = '';
      theFigureNumberTitle = '';
      return
   end
case -1   % Mouse move.
      a = theFigureName;
      b = theFigureNumberTitle;
      delete(theTextHandle)
      delete(theMarkerHandle)
      findpt(theLineHandle)
      theFigureName = a;
      theFigureNumberTitle = b;
      return
   otherwise
   end
end

switch get(theLine, 'Type')
case 'line'
otherwise
   if nargout > 0, theResult = []; end
   return
end

if nargin < 2
   theCurrentPoint = mean(get(gca, 'CurrentPoint'));   % Assume "view(2)".
   x = theCurrentPoint(1);
   y = theCurrentPoint(2);
   z = theCurrentPoint(3);
end

theXRange = diff(get(gca, 'XLim'));
theYRange = diff(get(gca, 'YLim'));
theZRange = diff(get(gca, 'ZLim'));
theZRange = 1;   % Assume "view(2)".

theXData = get(theLine, 'XData');
theYData = get(theLine, 'YData');
theZData = get(theLine, 'ZData');
if isempty(theZData), theZData = zeros(size(theXData)); end
theZData = theZData .* 0;   % Assume "view(2)".

dx = (theXData - x) .* theYRange .* theZRange;
dy = (theYData - y) .* theXRange .* theZRange;
dz = (theZData - z) .* theXRange .* theYRange;

dd = dx.^2 + dy.^2 + dz.^2;

theIndex = find(dd == min(dd));
if any(theIndex), theIndex = theIndex(1); end

x = theXData(theIndex);
y = theYData(theIndex);
z = theZData(theIndex);

result = [theLine, theIndex, x, y, z];

if nargout > 1
   theResult = theLine;
elseif nargout == 1
   theResult = result;
else
   assignin('base', 'ans', result)
   theString = ['<'num2str(x, DIGITS) ', ' num2str(y, DIGITS) '>'];
   theFigureName = get(gcf, 'Name');
   theFigureNumberTitle = get(gcf, 'NumberTitle');
   set(gcf, 'Name', theString, 'NumberTitle', 'off')
   theMarker = get(theLine, 'Marker');
   theColor = get(theLine, 'Color');
   switch theMarker
   case 'o'
      theMarker = '*';
   otherwise
      theMarker = 'o';
   end
   theLineHandle = theLine;
   theMarkerHandle = line(x, y, ...
                          'Marker', theMarker, ...
                          'EraseMode', 'xor');
   theTextHandle = text(x, y, theString, ...
                        'Tag', mfilename, 'EraseMode', 'xor', ...
                        'HorizontalAlignment', 'right', ...
                        'VerticalAlignment', 'bottom');
   set(gcf, 'WindowButtonMotionFcn', 'findpt(-1)')
   set(gcf, 'WindowButtonUpFcn', 'findpt(0)')
end
