function generator = mpb ( ndim, n, generator, npp )

%*****************************************************************************80
%
%% mpb() projects generators onto the boundary of the region.
%
%  Discussion:
%
%    The number NPP sets the number of subintervals into which we subdivide
%    the boundary.  It does NOT specify how many points will be pulled onto
%    the boundary.  The reason for this is that, after the first boundary
%    subinterval has had a generator pulled into it, on every subsequent
%    subinterval the nearest generator is likely to be the one in the
%    previous subinterval!  Unless an interior generator is closer than
%    some small distance, this process will simply drag some unfortunate
%    generator onto the boundary, and then around from interval to interval
%    for a considerable time.
%
%    The algorithm could be changed, if desired, so that points snapped
%    to the boundary are guaranteed not to move, at least not twice in
%    one application of this routine!
%
%  Licensing:
%
%    This code is distributed under the MIT license.
%
%  Modified:
%
%    02 December 2004
%
%  Author:
%
%    Lili Ju
%
%  Input:
%
%    Input, integer NDIM, the spatial dimension.
%
%    Input, integer N, the number of generators.
%
%    Input, real GENERATOR(NDIM,N), the coordinates of
%    the generators.  On some generators will have been moved.
%
%    Input, integer NPP, the number of subintervals into which the
%    perimeter is divided.
%
%  Output:
%
%    real GENERATOR(NDIM,N), the updated coordinates of the generators.
%
  dx = 1.0;
  dy = 1.0;
%
%  HH is the length of an individual segment of the perimeter of the region.
%
%  U is set in such a way that on step I, it measures the distance from
%  the lower left corner of the box to the midpoint of the I-th subinterval
%  on the perimeter of the box.
%
  hh = 2.0 * ( dx + dy ) / npp;

  u = -0.5 * hh;

  for i = 1 : npp

    u = u + hh;
%
%  The portion of the bottom perimeter from (0,0) to (1,0).
%
    if ( u < dx )
      sample(1:2,1) = [ u, 0.0 ]';
      nearest = find_closest ( ndim, n, 1, sample, generator );
      generator(2,nearest(1)) = 0.0;
%
%  The portion of the right perimeter from (1,0) to (1,1).
%
    elseif ( dx < u && u < dx + dy )
      sample(1:2,1) = [ 1.0, ( u - dx ) ]';
      nearest = find_closest ( ndim, n, 1, sample, generator );
      generator(1,nearest(1)) = 1.0;
%
%  The portion of the top perimeter from (1,1) to (0,1).
%
    elseif ( dx + dy < u && u < dx + dy + dx )
      sample(1:2,1) = [ 1.0 - ( u - dx - dy ), 1.0 ]';
      nearest = find_closest ( ndim, n, 1, sample, generator );
      generator(2,nearest(1)) = 1.0;
%
%  The portion of the left perimeter from (0,1) to (0,0).
%
    elseif ( dx + dy + dx < u )
      sample(1:2,1) = [ 0.0, 1.0 - ( u - dx - dy - dx ) ]';
      nearest = find_closest ( ndim, n, 1, sample, generator );
      generator(1,nearest(1)) = 0.0;
    end

  end

  return
end
