docs: def close_curves(*crvs, **kw):
      '''
      close_curves(crv1, crv2...) yields a single curve that merges all of the given list of curves
        together. The curves must be given in order, such that the i'th curve should be connected to
        to the (i+1)'th curve circularly to form a perimeter.
  
      The following optional parameters may be given:
        * grid may specify the number of grid-points to use in the initial search for a start-point
          (default: 16).
        * order may specify the order of the resulting curve; by default (None) uses the lowest order
          of all curves.
        * smoothing (None) the amount to smooth the points.
        * even_out (True) whether to even out the distances along the curve.
        * meta_data (None) an optional map of meta-data to give the spline representation.
      '''
      for k in six.iterkeys(kw):
          if k not in close_curves.default_options: raise ValueError('Unrecognized option: %s' % k)
      kw = {k:(kw[k] if k in kw else v) for (k,v) in six.iteritems(close_curves.default_options)}
      (grid, order) = (kw['grid'], kw['order'])
      crvs = [(crv if is_curve_spline(crv) else to_curve_spline(crv)).even_out() for crv in crvs]
      # find all intersections:
      isects = [curve_intersection(u,v, grid=grid)
                for (u,v) in zip(crvs, np.roll(crvs,-1))]
      # subsample curves
      crds = np.hstack([crv.subcurve(s1[1], s0[0]).coordinates[:,:-1]
                        for (crv,s0,s1) in zip(crvs, isects, np.roll(isects,1,0))])
      kw['order'] = np.min([crv.order for crv in crvs]) if order is None else order
      kw = {k:v for (k,v) in six.iteritems(kw)
            if v is not None and k in ('order','smoothing','even_out','meta_data')}
      return curve_spline(crds, periodic=True, **kw)