Video thumbnail
A View of it Coming Together
This video gives an overview of how the remaining 5 videos connect the pieces for the Marching Cubes algorithm. Please consider becoming a member to support the creation of these tutorials and everything else on this website. We appreciate your support more than you know.

Back to Marching Cubes
Code
Below is the quick script we used to match our rotated cube corner points with our original 8 cube corner points.
    
// Grasshopper Script Instance
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;

using Rhino;
using Rhino.Geometry;

using Grasshopper;
using Grasshopper.Kernel;
using Grasshopper.Kernel.Data;
using Grasshopper.Kernel.Types;

public class Script_Instance : GH_ScriptInstance
{  
  private void RunScript(
	IList<Point3d> cube_pts,
	DataTree<Point3d> trans_pts,
	ref object a)
  {
    DataTree<int> map_indices = new DataTree<int>();

    for (int i = 0; i < trans_pts.BranchCount / 8; i++)
    {
      GH_Path pth = new GH_Path(i);
      for (int j = 0; j < 8; j++)
      {
        for (int k = 0; k < cube_pts.Count; k++)
        {
          Point3d pt_A = trans_pts.Branch(i, j)[0];
          Point3d pt_B = cube_pts[k];
          if (IsEqual(pt_A, pt_B)) map_indices.Add(k, pth);
        }
      }
    }

    a = map_indices;
  }

  public bool IsEqual(Point3d a, Point3d b)
  {
    bool equal = false;

    double Ax = a.X;
    double Ay = a.Y;
    double Az = a.Z;

    double Bx = b.X;
    double By = b.Y;
    double Bz = b.Z;

    double diff = Math.Abs(Ax - Bx) + Math.Abs(Ay - By) + Math.Abs(Az - Bz);

    if (diff < 0.01) equal = true;

    return equal;
  }
}
  
If you prefer to the code in separated snippets, here is the script inside the RunScript function:
    
DataTree<int> map_indices = new DataTree<int>();

for (int i = 0; i < trans_pts.BranchCount / 8; i++)
    {
      GH_Path pth = new GH_Path(i);
      for (int j = 0; j < 8; j++)
      {
        for (int k = 0; k < cube_pts.Count; k++)
        {
          Point3d pt_A = trans_pts.Branch(i, j)[0];
          Point3d pt_B = cube_pts[k];
          if (IsEqual(pt_A, pt_B)) map_indices.Add(k, pth);
        }
      }
    }

a = map_indices;
  
And here is the IsEqual function, checking to see if Point3d a is equal to Point3d b:
    
public bool IsEqual(Point3d a, Point3d b)
  {
    bool equal = false;

    double Ax = a.X;
    double Ay = a.Y;
    double Az = a.Z;

    double Bx = b.X;
    double By = b.Y;
    double Bz = b.Z;

    double diff = Math.Abs(Ax - Bx) + Math.Abs(Ay - By) + Math.Abs(Az - Bz);

    if (diff < 0.01) equal = true;

    return equal;
  }
  
And finally, the code block below holds the C# script for the component that organizes our meshes according to their Boolean patterns. It takes in a mesh DataTree and a Boolean patterns DataTree (well, 2 of each actually—the duplicates are our NOT Boolean patterns and our flipped meshes), and it puts each mesh into a new DataTree in a branch designated by its associated Boolean pattern.
    
// Grasshopper Script Instance
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;

using Rhino;
using Rhino.Geometry;

using Grasshopper;
using Grasshopper.Kernel;
using Grasshopper.Kernel.Data;
using Grasshopper.Kernel.Types;

public class Script_Instance : GH_ScriptInstance
{ 
  private void RunScript(
	DataTree<Mesh> meshes,
	DataTree<int> patterns,
	DataTree<Mesh> n_meshes,
	DataTree<int> n_patterns,
	ref object a)
  {
    DataTree<Mesh> all_meshes = new DataTree<Mesh>();

    GH_Path zeros = new GH_Path(0,0,0,0,0,0,0,0);
    GH_Path ones = new GH_Path(1,1,1,1,1,1,1,1);

    all_meshes.EnsurePath(zeros);
    all_meshes.EnsurePath(ones);

    for (int i = 0; i < meshes.BranchCount; i++)
    {
      for (int j = 0; j < meshes.Branch(i).Count; j++)
      {
        GH_Path pth = new GH_Path(
          patterns.Branch(i,j)[0],
          patterns.Branch(i,j)[1],
          patterns.Branch(i,j)[2],
          patterns.Branch(i,j)[3],
          patterns.Branch(i,j)[4],
          patterns.Branch(i,j)[5],
          patterns.Branch(i,j)[6],
          patterns.Branch(i,j)[7]
          );
        Mesh nx_mesh = new Mesh();
        nx_mesh = meshes.Branch(i)[j];
        all_meshes.Add(nx_mesh, pth);
      }
    }

    for (int i = 0; i < n_meshes.BranchCount; i++)
    {
      for (int j = 0; j < n_meshes.Branch(i).Count; j++)
      {
        GH_Path pth = new GH_Path(
          n_patterns.Branch(i, j)[0],
          n_patterns.Branch(i, j)[1],
          n_patterns.Branch(i, j)[2],
          n_patterns.Branch(i, j)[3],
          n_patterns.Branch(i, j)[4],
          n_patterns.Branch(i, j)[5],
          n_patterns.Branch(i, j)[6],
          n_patterns.Branch(i, j)[7]
          );
        Mesh nx_mesh = new Mesh();
        nx_mesh = n_meshes.Branch(i)[j];
        all_meshes.Add(nx_mesh, pth);
      }
    }

    a = all_meshes;
  }
}