In this video we finish the lookup table. This involves matching transformed meshes to transformed cube corners; then rearranging our original 14 Boolean patterns to match the cube corners transformations; then placing all of our meshes (we will have too many) into branches that are designated by their associated Boolean patterns; and finally, selecting the first mesh from each branch (since all meshes in each branch will be identical). This will give us a component that contains 256 branches—2 of which are null, 254 of which are the 254 possible meshes (ignoring ambiguous cases) for any combination of ‘inside’ or ‘outside’ cube corners.
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;
}
}