docs: def _project_on_ellipsoid(c, r, locations):
      """displace locations to the nearest point on ellipsoid surface"""
      p0 = locations - c  # original locations
  
      l2 = 1 / np.sum(p0**2 / r**2, axis=1, keepdims=True)
      p = p0 * np.sqrt(l2)  # initial approximation (projection of points towards center of ellipsoid)
  
      fun = lambda x: np.sum((x.reshape(p0.shape) - p0)**2)              # minimize distance between new and old points
      con = lambda x: np.sum(x.reshape(p0.shape)**2 / r**2, axis=1) - 1  # new points constrained to surface of ellipsoid
      res = sp.optimize.minimize(fun, p, constraints={'type': 'eq', 'fun': con}, method='SLSQP')
  
      return res['x'].reshape(p0.shape) + c