function [ pn, qn ] = lines_exp_near_3d ( p1, p2, q1, q2 )

%*****************************************************************************80
%
%% lines_exp_near_3d() computes nearest points on two explicit lines in 3D.
%
%  Discussion:
%
%    The explicit form of a line in 3D is:
%
%      the line through the points P1 and P2.
%
%    This routine uses a method that is essentially independent of dimension.
%
%  Licensing:
%
%    This code is distributed under the MIT license.
%
%  Modified:
%
%    09 November 2016
%
%  Author:
%
%    John Burkardt
%
%  Input:
%
%    real P1(3,1), P2(3,1), two points on the first line.
%
%    real Q1(3,1), Q2(3,1), two points on the second line.
%
%  Output:
%
%    real PN(3,1), QN(3,1), nearest points on the lines.
%
  p1 = p1(:);
  p2 = p2(:);
  q1 = q1(:);
  q2 = q2(:);

  dim_num = 3;
%
%  Let U = (P2-P1) and V = (Q2-Q1) be the direction vectors on
%  the two lines.
%
  u(1:dim_num,1) = p2(1:dim_num,1) - p1(1:dim_num,1);
  v(1:dim_num,1) = q2(1:dim_num,1) - q1(1:dim_num,1);
%
%  Let SN be the unknown coordinate of the nearest point PN on line 1,
%  so that PN = P(SN) = P1 + SN * (P2-P1).
%
%  Let TN be the unknown coordinate of the nearest point QN on line 2,
%  so that QN = Q(TN) = Q1 + TN * (Q2-Q1).
%
%  Let W0 = (P1-Q1).
%
  w0(1:dim_num,1) = p1(1:dim_num,1) - q1(1:dim_num,1);
%
%  The vector direction WC = P(SN) - Q(TC) is unique (among directions)
%  perpendicular to both U and V, so
%
%    U dot WC = 0
%    V dot WC = 0
%
%  or, equivalently:
%
%    U dot ( P1 + SN * (P2 - P1) - Q1 - TN * (Q2 - Q1) ) = 0
%    V dot ( P1 + SN * (P2 - P1) - Q1 - TN * (Q2 - Q1) ) = 0
%
%  or, equivalently:
%
%    (u dot u ) * sn - (u dot v ) tc = -u * w0
%    (v dot u ) * sn - (v dot v ) tc = -v * w0
%
%  or, equivalently:
%
%   ( a  -b ) * ( sn ) = ( -d )
%   ( b  -c )   ( tc )   ( -e )
%
  a = u' * u;
  b = u' * v;
  c = v' * v;
  d = u' * w0;
  e = v' * w0;
%
%  Check the determinant.
%
  det = - a * c + b * b;

  if ( det == 0.0 )
    sn = 0.0;
    if ( abs ( b ) < abs ( c ) )
      tn = e / c;
    else
      tn = d / b;
    end
  else
    sn = ( c * d - b * e ) / det;
    tn = ( b * d - a * e ) / det;
  end

  pn(1:dim_num,1) = p1(1:dim_num,1) + sn * ( p2(1:dim_num,1) - p1(1:dim_num,1) );
  qn(1:dim_num,1) = q1(1:dim_num,1) + tn * ( q2(1:dim_num,1) - q1(1:dim_num,1) );

  return
end
