function [ hull_num, hull ] = points_hull_2d ( node_num, node_xy )

%*****************************************************************************80
%
%% points_hull_2d() computes the convex hull of a set of points in 2D.
%
%  Licensing:
%
%    This code is distributed under the MIT license.
%
%  Modified:
%
%    25 June 2009
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer NODE_NUM, the number of nodes.
%
%    Input, real NODE_XY(2,NODE_NUM), the coordinates of the nodes.
%
%    Output, integer HULL_NUM, the number of nodes that lie on the convex hull.
%
%    Output, integer HULL(HULL_NUM).  The first HULL_NUM entries contain
%    the indices of the nodes that form the convex hull, in order.
%    These indices are 1-based, not 0-based!
%
  dim_num = 2;

  if ( node_num < 1 )
    hull_num = 0;
    return
  end
%
%  If NODE_NUM = 1, the hull is the point.
%
  if ( node_num == 1 )
    hull_num = 1;
    hull(1) = 1;
    return
  end
%
%  If NODE_NUM = 2, then the convex hull is either the two distinct points,
%  or possibly a single (repeated) point.
%
  if ( node_num == 2 )

    if ( any ( node_xy(1:dim_num,1) ~= node_xy(1:dim_num,2) ) )
      hull_num = 2;
      hull(1) = 1;
      hull(2) = 2;
    else
      hull_num = 1;
      hull(1) = 1;
    end

    return

  end
%
%  Find the leftmost point and call it Q.
%  In case of ties, take the bottom-most.
%
  q = 1;
  for i = 2 : node_num
    if ( node_xy(1,i) < node_xy(1,q) || ...
       ( node_xy(1,i) == node_xy(1,q) && node_xy(2,i) < node_xy(2,q) ) )
      q = i;
    end
  end

  q_xy(1:2) = node_xy(1:2,q);
%
%  Remember the starting point.
%
  first = q;
  hull_num = 1;
  hull(1) = q;
%
%  For the first point, make a fictitious previous point, 1 unit south,
%  and call it "P".
%
  p_xy(1) = q_xy(1);
  p_xy(2) = q_xy(2) - 1.0;
%
%  Now, having old point P, and current point Q, find the new point R
%  so the angle PQR is maximal.
%
%  Watch out for the possibility that the two nodes are identical.
%
  while ( true )

    r = 0;
    angle_max = 0.0;

    for i = 1 : node_num

      if ( i ~= q && ...
           ( node_xy(1,i) ~= q_xy(1) || node_xy(2,i) ~= q_xy(2) ) )

        angle = angle_rad_2d ( p_xy, q_xy, node_xy(1:2,i) );

        if ( r == 0 || angle_max < angle )

          r = i;
          r_xy(1:2) = node_xy(1:2,r);
          angle_max = angle;
%
%  In case of ties, choose the nearer point.
%
        elseif ( r ~= 0 && angle == angle_max )

          di = ( node_xy(1,i) - q_xy(1) )^2 + ( node_xy(2,i) - q_xy(2) )^2;
          dr = ( r_xy(1)      - q_xy(1) )^2 + ( r_xy(2)      - q_xy(2) )^2;

          if ( di < dr )
            r = i;
            r_xy(1:2) = node_xy(1:2,r);
            angle_max = angle;
          end

        end

      end

    end
%
%  If we've returned to our starting point, exit.
%
    if ( r == first )
      break
    end

    hull_num = hull_num + 1;

    if ( node_num < hull_num )
      fprintf ( 1, '\n' );
      fprintf ( 1, 'POINTS_HULL_2D - Fatal error!\n' );
      fprintf ( 1, '  The algorithm failed.\n' );
      error ( 'POINTS_HULL_2D - Fatal error!' );
    end
%
%  Add point R to the convex hull.
%
    hull(hull_num) = r;
%
%  Set Q := P, P := R, and repeat.
%
    q = r;

    p_xy(1:2) = q_xy(1:2);
    q_xy(1:2) = r_xy(1:2);

  end

  return
end
