function [ do_intersect, are_parallel, x, alpha, beta ] = intersect_half_lines( a, u, b, v, epsilon )
  
%  function [ do_intersect, are_parallel, x, alpha, beta ] = intersect_half_lines( a, u, b, v, epsilon )
%
% Find the intersection (if any) of two half lines:
%    x = a + alpha * u,   alpha > 0
%    x = b + beta  * v,   beta  > 0
% 
%   Inputs: 
%
% The 2-by-1 vectors a and b are the starting point of each half-line.
% The 2-by-1 vectors u and v are the directions of each half-line.
%
% Optionally, epsilon is a very small value for equality tests
% ( default 1e-10).
%
%
%   Outputs:
%
% do_intersect and are_parallel are binary flags (0 or 1).
%
% The 2-by-1 vector x is defined only when do_intersect == 1 and
% are_parallel == 0 otherwise a [] value is returned.
%
% --- G. Lathoud 2005
  
  
  if nargin < 4
    error( [ mfilename ' needs at least 4 input arguments.' ] );
  end
  
  if ~exist( 'epsilon', 'var' )
    epsilon = 1e-10;
  end
  
  % Make sure we have 2 x 1 column vectors
  % ( throwing errors makes it easier to debug higher-level code. )
  if ~all( size( a ) == [ 2 1 ] )
    error( [ mfilename ': input argument "u" must be a 2 x 1 vector.' ] );
  end
  
  if ~all( size( u ) == [ 2 1 ] )
    error( [ mfilename ': input argument "u" must be a 2 x 1 vector.' ] );
  end
  
  if ~all( size( b ) == [ 2 1 ] )
    error( [ mfilename ': input argument "b" must be a 2 x 1 vector.' ] );
  end
  
  if ~all( size( v ) == [ 2 1 ] )
    error( [ mfilename ': input argument "v" must be a 2 x 1 vector.' ] );
  end
  
    
  delta = b - a;

  % Potential intersection point
  %      x = a + alpha * u
  % and  x = b + beta * v
  %
  % In case that there is no intersection, we return [].
  
  x = [];
  alpha = [];
  beta = [];
  
  % Are they parallel?
  
  DELTA = det( [ u, -v ] );
  
  are_parallel   = ( abs( DELTA ) < epsilon );
  
  
  do_intersect   = 0;
  
  if are_parallel
    
    % Check whether the supporting lines intersect
    do_intersect = abs( det( [ u, delta ] ) ) < epsilon;
    
    if do_intersect
      
      % Check whether the parallel half-lines intersect, which amounts
      % to exclude only one case: 
      %
      % "opposite directions u,v" and "the middle (a+b)/2 does not
      % belong to at least one of the half-lines."
      
      middle = ( a + b ) / 2;
      
      do_intersect = ~( ( dot( u, v ) < epsilon ) & ( ( dot( middle - a, u ) < epsilon ) | ( dot( middle - b, v ) < epsilon ) ) );
      
    end
    
  else
    
    % Not parallel: find the intersection point of the supporting lines
    alpha = det( [ delta, -v ] ) / DELTA;
    beta  = det( [ u, delta  ] ) / DELTA;
    
    % Check whether the intersection point belongs to both half-lines
    do_intersect = ( alpha > -epsilon ) & ( beta > -epsilon );
  
    if do_intersect
      % "mean" to reduce numerical imprecision errors
      x = mean( [ a + alpha * u,    b + beta * v ], 2 );
    end
    
  end
  
  