Site Tools


Passing Arrays from .NET to RhinoScript

Version: Rhino 4

Question

I have a standalone C# application that automates Rhino by creating a Rhino4.Application object and then obtaining a reference to the RhinoScript COM object. I can perform simple operations, such as scripting commands via the Command method and adding lines via the AddLine method. But I am unable to use any RhinoScript method where I need to pass in an array of 3D points, which in RhinoScript are really arrays of arrays of doubles. Is there a way to call RhinoScript's AddMesh method from C#?

Answer

Simple data types, such as integers and doubles are easily marshalled between .NET and COM because their values can be easily converted to the Object .NET data type. Array are a little more difficult to deal with, but not impossible. The .NET array classes have a ToArray member that will copy the elements of the array to a new Object array. A .NET Object array will marshall to COM as a SafeArray.

The following example demonstrates how to call RhinoScript's AddMesh method from a standalone application:

C#

static void Main(string[] args)
{
  //Create Rhino application object
  Console.Write("Creating Rhino object...");
  Rhino4.Application objRhino = new Rhino4.Application();
  if (objRhino == null)
  {
    Console.WriteLine("failed.");
    return;
  }
  else
  {
    Console.WriteLine("succeeded.");
  }
 
  //Retrieve RhinoScript object
  Console.Write("Retrieving RhinoScript object...");
  RhinoScript4.IRhinoScript objRhinoScript = null;
  int count = 0;
  System.Threading.Thread.Sleep(500);
  while (count < 10)
  {
    object obj = objRhino.GetScriptObject();
    if (obj != null)
    {
      objRhinoScript = (RhinoScript4.IRhinoScript)obj;
      if (objRhinoScript != null)
        break;
    }
    System.Threading.Thread.Sleep(500);
    count++;
  }
  if (objRhinoScript == null)
  {
    Console.WriteLine("failed.");
    return;
  }
  else
  {
    Console.WriteLine("succeeded.");
  }
 
  //Create mesh data
  Console.Write("Adding mesh object...");
 
  //Mesh vertices
  ArrayList vertices = new ArrayList();
  ArrayList v0 = new ArrayList();
  v0.Add(0.0);
  v0.Add(0.0);
  v0.Add(0.0);
  vertices.Add(v0.ToArray());
 
  ArrayList v1 = new ArrayList();
  v1.Add(10.0);
  v1.Add(0.0);
  v1.Add(0.0);
  vertices.Add(v1.ToArray());
 
  ArrayList v2 = new ArrayList();
  v2.Add(10.0);
  v2.Add(10.0);
  v2.Add(0.0);
  vertices.Add(v2.ToArray());
 
  ArrayList v3 = new ArrayList();
  v3.Add(0.0);
  v3.Add(10.0);
  v3.Add(0.0);
  vertices.Add(v3.ToArray());
 
  //Mesh faces
  ArrayList faces = new ArrayList();
  ArrayList f0 = new ArrayList();
  f0.Add(0);
  f0.Add(1);
  f0.Add(2);
  f0.Add(3);
  faces.Add(f0.ToArray());
 
  //Mesh normals
  ArrayList normals = new ArrayList();
  ArrayList n0 = new ArrayList();
  n0.Add(0.0);
  n0.Add(0.0);
  n0.Add(1.0);
  normals.Add(n0.ToArray());
 
  ArrayList n1 = new ArrayList();
  n1.Add(0.0);
  n1.Add(0.0);
  n1.Add(1.0);
  normals.Add(n1.ToArray());
 
  ArrayList n2 = new ArrayList();
  n2.Add(0.0);
  n2.Add(0.0);
  n2.Add(1.0);
  normals.Add(n2.ToArray());
 
  ArrayList n3 = new ArrayList();
  n3.Add(0.0);
  n3.Add(0.0);
  n3.Add(1.0);
  normals.Add(n3.ToArray());
 
  //Texture coordinates
  ArrayList textures = new ArrayList();
  ArrayList t0 = new ArrayList();
  t0.Add(0.0);
  t0.Add(0.0);
  textures.Add(t0.ToArray());
 
  ArrayList t1 = new ArrayList();
  t1.Add(1.0);
  t1.Add(0.0);
  textures.Add(t1.ToArray());
 
  ArrayList t2 = new ArrayList();
  t2.Add(1.0);
  t2.Add(1.0);
  textures.Add(t2.ToArray());
 
  ArrayList t3 = new ArrayList();
  t3.Add(0.0);
  t3.Add(0.1);
  textures.Add(t3.ToArray());
 
  //Vertex colors
  ArrayList colors = new ArrayList();
  colors.Add(0);
  colors.Add(0);
  colors.Add(0);
  colors.Add(0);
 
  //Call AddMesh
  //If you want to pass in everything, then do this:
 
  object obj_uuid_str = objRhinoScript.AddMesh(
          vertices.ToArray(),
          faces.ToArray(),
          normals.ToArray(),
          textures.ToArray(),
          colors.ToArray()
          );
 
  //If you do not want to pass in optional argument,
  //then pass "System.Reflection.Missing.Value".
 
  object obj_uuid_str = objRhinoScript.AddMesh(
         vertices.ToArray(),
         faces.ToArray(),
         System.Reflection.Missing.Value,
         System.Reflection.Missing.Value,
         System.Reflection.Missing.Value
         );
 
  Console.WriteLine(obj_uuid_str.ToString());
 
  //Save the file
  Console.WriteLine("Saving test file.");
  objRhinoScript.Command("_-Save c:\\test.3dm", 0);
  Console.WriteLine("Done!");
}
developer/dotnettorhinoscript2.txt ยท Last modified: 2016/04/04 by sandy