/// <summary>
    /// Constructs a rolling ball fillet between two surfaces.
    /// </summary>
    /// <param name="surfaceA">A first surface.</param>
    /// <param name="uvA">A point in the parameter space of FaceA near where the fillet is expected to hit the surface.</param>
    /// <param name="surfaceB">A second surface.</param>
    /// <param name="uvB">A point in the parameter space of FaceB near where the fillet is expected to hit the surface.</param>
    /// <param name="radius">A radius value.</param>
    /// <param name="tolerance">A tolerance value used for approximating and intersecting offset surfaces.</param>
    /// <returns>A new array of rolling ball fillet surfaces; this array can be empty on failure.</returns>
    /// <exception cref="ArgumentNullException">If surfaceA or surfaceB are null.</exception>
    public static Surface[] CreateRollingBallFillet(Surface surfaceA, Point2d uvA, Surface surfaceB, Point2d uvB, double radius, double tolerance)
    {
      if (surfaceA == null) throw new ArgumentNullException("surfaceA");
      if (surfaceB == null) throw new ArgumentNullException("surfaceB");

      IntPtr pConstSurfaceA = surfaceA.ConstPointer();
      IntPtr pConstSurfaceB = surfaceB.ConstPointer();
      using (Runtime.InteropWrappers.SimpleArraySurfacePointer srfs = new Rhino.Runtime.InteropWrappers.SimpleArraySurfacePointer())
      {
        IntPtr pSurfaces = srfs.NonConstPointer();
        UnsafeNativeMethods.RHC_RhinoSimpleRollingBallFillet2(pConstSurfaceA, uvA,
          pConstSurfaceB, uvB, radius, tolerance, pSurfaces);
        return srfs.ToNonConstArray();
      }
    }
 /// <summary>
 /// Constructs a periodic surface from a base surface and a direction.
 /// </summary>
 /// <param name="baseSurface">A base surface.</param>
 /// <param name="direction">0 is first parameter, 1 is second parameter.</param>
 /// <returns>A new surface; or null on error.</returns>
 public static Surface CreatePeriodicSurface(Surface baseSurface, int direction)
 {
   IntPtr pConstSurface = baseSurface.ConstPointer();
   IntPtr pNewSurf = UnsafeNativeMethods.TL_Surface_MakePeriodic(pConstSurface, direction);
   return GeometryBase.CreateGeometryHelper(pNewSurf, null) as Surface;
 }
 /// <summary>
 /// Finds a curve by offsetting an existing curve normal to a surface.
 /// The caller is responsible for ensuring that the curve lies on the input surface.
 /// </summary>
 /// <param name="surface">Surface from which normals are calculated.</param>
 /// <param name="height">offset distance (distance from surface to result curve)</param>
 /// <returns>
 /// Offset curve at distance height from the surface.  The offset curve is
 /// interpolated through a small number of points so if the surface is irregular
 /// or complicated, the result will not be a very accurate offset.
 /// </returns>
 public Curve OffsetNormalToSurface(Surface surface, double height)
 {
   IntPtr pConstThis = ConstPointer();
   IntPtr pConstSurface = surface.ConstPointer();
   IntPtr pOffsetCurve = UnsafeNativeMethods.RHC_RhinoOffsetCurveNormal(pConstThis, pConstSurface, height);
   return GeometryBase.CreateGeometryHelper(pOffsetCurve, null) as Curve;
 }
 /// <summary>
 /// Splits a curve into pieces using a surface.
 /// </summary>
 /// <param name="cutter">A cutting surface or polysurface.</param>
 /// <param name="tolerance">A tolerance for computing intersections.</param>
 /// <returns>An array of curves. This array can be empty.</returns>
 public Curve[] Split(Surface cutter, double tolerance)
 {
   IntPtr pConstThis = ConstPointer();
   IntPtr pConstSurface = cutter.ConstPointer();
   using (Rhino.Runtime.InteropWrappers.SimpleArrayCurvePointer pieces = new SimpleArrayCurvePointer())
   {
     IntPtr pPieces = pieces.NonConstPointer();
     UnsafeNativeMethods.RHC_RhinoCurveSplit(pConstThis, pConstSurface, tolerance, pPieces);
     return pieces.ToNonConstArray();
   }
 }
    /// <summary>
    /// Compute the VolumeMassProperties for a single Surface.
    /// </summary>
    /// <param name="surface">Surface to measure.</param>
    /// <returns>The VolumeMassProperties for the given Surface or null on failure.</returns>
    /// <exception cref="System.ArgumentNullException">When surface is null.</exception>
    public static VolumeMassProperties Compute(Surface surface)
    {
      if (surface == null)
        throw new ArgumentNullException("surface");

      IntPtr pSurface = surface.ConstPointer();
      const double relativeTolerance = 1.0e-6;
      const double absoluteTolerance = 1.0e-6;
      IntPtr rc = UnsafeNativeMethods.ON_Surface_MassProperties(false, pSurface, relativeTolerance, absoluteTolerance);
      return IntPtr.Zero == rc ? null : new VolumeMassProperties(rc, false);
    }
 /// <summary>
 /// Constructs a periodic surface from a base surface and a direction.
 /// </summary>
 /// <param name="baseSurface">A base surface.</param>
 /// <param name="direction">0 is first parameter, 1 is second parameter.</param>
 /// <returns>A new surface; or null on error.</returns>
 public static Surface CreatePeriodicSurface(Surface baseSurface, int direction)
 {
   IntPtr const_ptr_surface = baseSurface.ConstPointer();
   IntPtr ptr_new_surface = UnsafeNativeMethods.TL_Surface_MakePeriodic(const_ptr_surface, direction);
   return CreateGeometryHelper(ptr_new_surface, null) as Surface;
 }
    /// <summary>
    /// Constructs a rolling ball fillet between two surfaces.
    /// </summary>
    /// <param name="surfaceA">A first surface.</param>
    /// <param name="flipA">A value that indicates whether A should be used in flipped mode.</param>
    /// <param name="surfaceB">A second surface.</param>
    /// <param name="flipB">A value that indicates whether B should be used in flipped mode.</param>
    /// <param name="radius">A radius value.</param>
    /// <param name="tolerance">A tolerance value.</param>
    /// <returns>A new array of rolling ball fillet surfaces; this array can be empty on failure.</returns>
    /// <exception cref="ArgumentNullException">If surfaceA or surfaceB are null.</exception>
    public static Surface[] CreateRollingBallFillet(Surface surfaceA, bool flipA, Surface surfaceB, bool flipB, double radius, double tolerance)
    {
      if (surfaceA == null) throw new ArgumentNullException("surfaceA");
      if (surfaceB == null) throw new ArgumentNullException("surfaceB");

      IntPtr const_ptr_surface_a = surfaceA.ConstPointer();
      IntPtr const_ptr_surface_b = surfaceB.ConstPointer();
      using (Runtime.InteropWrappers.SimpleArraySurfacePointer srfs = new Runtime.InteropWrappers.SimpleArraySurfacePointer())
      {
        IntPtr ptr_surfaces = srfs.NonConstPointer();
        UnsafeNativeMethods.RHC_RhinoSimpleRollingBallFillet(const_ptr_surface_a, flipA,
          const_ptr_surface_b, flipB, radius, tolerance, ptr_surfaces);
        return srfs.ToNonConstArray();
      }
    }