/// <summary>
    /// Executes unrolling operations.
    /// </summary>
    /// <param name="unrolledCurves">An array of unrolled curves is assigned during the call in this out parameter.</param>
    /// <param name="unrolledPoints">An array of unrolled points is assigned during the call in this out parameter.</param>
    /// <param name="unrolledDots">An array of unrolled text dots is assigned during the call in this out parameter.</param>
    /// <returns>An array of breps. This array can be empty.</returns>
    public Brep[] PerformUnroll(out Curve[] unrolledCurves, out Point3d[] unrolledPoints, out TextDot[] unrolledDots)
    {
      unrolledCurves = new Curve[0];
      unrolledPoints = new Point3d[0];
      unrolledDots = new TextDot[0];

      IntPtr pUnroller = IntPtr.Zero;
      if (m_surface != null)
      {
        IntPtr pSurface = m_surface.ConstPointer();
        pUnroller = UnsafeNativeMethods.CRhinoUnroll_NewSrf(pSurface, m_dAbsoluteTolerance, m_dRelativeTolerance);
      }
      else if (m_brep != null)
      {
        IntPtr pBrep = m_brep.ConstPointer();
        pUnroller = UnsafeNativeMethods.CRhinoUnroll_NewBrp(pBrep, m_dAbsoluteTolerance, m_dRelativeTolerance);
      }
      if (pUnroller == IntPtr.Zero)
        throw new Exception("Unable to access input surface or brep");

      Brep[] rc = new Brep[0];
      if (0 == UnsafeNativeMethods.CRhinoUnroll_PrepareFaces(pUnroller))
      {
        if (m_curves.Count > 0)
        {
          Runtime.InteropWrappers.SimpleArrayCurvePointer crvs = new Rhino.Runtime.InteropWrappers.SimpleArrayCurvePointer(m_curves);
          IntPtr pCrvs = crvs.ConstPointer();
          UnsafeNativeMethods.CRhinoUnroll_PrepareCurves(pUnroller, pCrvs);
        }
        if (m_points.Count > 0)
        {
          Point3d[] pts =  m_points.ToArray();
          UnsafeNativeMethods.CRhinoUnroll_PreparePoints(pUnroller, pts.Length, pts);
        }
        if (m_dots.Count > 0)
        {
          Runtime.INTERNAL_GeometryArray dots = new Rhino.Runtime.INTERNAL_GeometryArray(m_dots);
          IntPtr pDots = dots.ConstPointer();
          UnsafeNativeMethods.CRhinoUnroll_PrepareDots(pUnroller, pDots);
        }

        int brepCount = 0;
        int curveCount = 0;
        int pointCount = 0;
        int dotCount = 0;
        double explode_dist = -1;
        if (m_bExplodeOutput)
          explode_dist = m_dExplodeSpacing;
        IntPtr pResults = UnsafeNativeMethods.CRhinoUnroll_CreateFlatBreps(pUnroller,
          explode_dist, ref brepCount, ref curveCount, ref pointCount, ref dotCount);
        if (pResults != IntPtr.Zero)
        {
          if (brepCount > 0)
          {
            rc = new Brep[brepCount];
            for (int i = 0; i < brepCount; i++)
            {
              IntPtr pBrep = UnsafeNativeMethods.CRhinoUnrollResults_GetBrep(pResults, i);
              if (pBrep != IntPtr.Zero) rc[i] = new Brep(pBrep, null);
            }
          }
          if (curveCount > 0)
          {
            unrolledCurves = new Curve[curveCount];
            for (int i = 0; i < curveCount; i++)
            {
              IntPtr pCurve = UnsafeNativeMethods.CRhinoUnrollResults_GetCurve(pResults, i);
              if (pCurve != IntPtr.Zero) unrolledCurves[i] = new Curve(pCurve, null);
            }
          }
          if (pointCount > 0)
          {
            unrolledPoints = new Point3d[pointCount];
            UnsafeNativeMethods.CRhinoUnrollResults_GetPoints(pResults, pointCount, unrolledPoints);
          }
          if (dotCount > 0)
          {
            unrolledDots = new TextDot[dotCount];
            for (int i = 0; i < dotCount; i++)
            {
              IntPtr pDot = UnsafeNativeMethods.CRhinoUnrollResults_GetDot(pResults, i);
              if (pDot != IntPtr.Zero) unrolledDots[i] = new TextDot(pDot, null);
            }
          }

          UnsafeNativeMethods.CRhinoUnrollResults_Delete(pResults);
        }
      }
      UnsafeNativeMethods.CRhinoUnroll_Delete(pUnroller);
      return rc;
    }
    /// <summary>
    /// Computes the Area properties for a collection of geometric objects. 
    /// At present only Breps, Surfaces, Meshes and Planar Closed Curves are supported.
    /// </summary>
    /// <param name="geometry">Objects to include in the area computation.</param>
    /// <returns>The Area properties for the entire collection or null on failure.</returns>
    public static AreaMassProperties Compute(IEnumerable<GeometryBase> geometry)
    {
      const double relativeTolerance = 1.0e-6;
      const double absoluteTolerance = 1.0e-6;

      Rhino.Runtime.INTERNAL_GeometryArray array = new Rhino.Runtime.INTERNAL_GeometryArray(geometry);
      IntPtr rc = UnsafeNativeMethods.ON_GeometryMassProperties(true, array.ConstPointer(), relativeTolerance, absoluteTolerance);
      return IntPtr.Zero == rc ? null : new AreaMassProperties(rc, false);
    }
    /// <summary>
    /// Computes point intersections that occur when shooting a ray to a collection of surfaces.
    /// </summary>
    /// <param name="ray">A ray used in intersection.</param>
    /// <param name="geometry">Only Surface and Brep objects are currently supported. Trims are ignored on Breps.</param>
    /// <param name="maxReflections">The maximum number of reflections. This value should be any value between 1 and 1000, inclusive.</param>
    /// <returns>An array of points: one for each face that was passed by the faceIds out reference.</returns>
    /// <exception cref="ArgumentNullException">geometry is null.</exception>
    /// <exception cref="ArgumentOutOfRangeException">maxReflections is strictly outside the [1-1000] range.</exception>
    public static Point3d[] RayShoot(Ray3d ray, IEnumerable<GeometryBase> geometry, int maxReflections)
    {
      if (geometry == null) throw new ArgumentNullException("geometry");
      if (maxReflections < 1 || maxReflections > 1000)
        throw new ArgumentOutOfRangeException("maxReflections", "maxReflections must be between 1-1000");
      // We should handle better the case of a null entry inside the geometry collection.
      // Currently a NullReferenceException occurs.

      Rhino.Runtime.INTERNAL_GeometryArray geom = new Rhino.Runtime.INTERNAL_GeometryArray(geometry);
      IntPtr pGeometry = geom.ConstPointer();
      Point3d[] rc = null;
      using (Rhino.Runtime.InteropWrappers.SimpleArrayPoint3d points = new Rhino.Runtime.InteropWrappers.SimpleArrayPoint3d())
      {
        IntPtr pPoints = points.NonConstPointer();
        int count = UnsafeNativeMethods.ON_RayShooter_ShootRay(ray.Position, ray.Direction, pGeometry, pPoints, maxReflections);
        if (count > 0) rc = points.ToArray();
      }
      geom.Dispose();
      return rc;
    }