“How about wind-blown sand?”

Euan’s suggestion of wind-blown sand was the subject of a few nervous giggles, especially when he suggested that the only way to do it “properly” might be to head to a beach with enough materials to make a 4m x 2.5m concrete mould.


But now that we’ve thought about it some more as a surface for tall kitchen cabinet doors we’re all getting quite excited about the prospect. What isn’t so clear is how to get from a general idea of what wind-blown sand should look like to a G-code file that we could send to a CNC machine.

Our first attempt to do this is a mathematical one based on the idea that the sand lines look like interference patterns of simple wavefronts.  Euan’s CAD tool of choice is Rhino so we used Grasshopper in Rhino and using a very small C# script to do the maths (although it could equally have been done in grasshopper itself).


This is all very well but the results are rather disappointingly regular and don’t have all of the characteristics of wind-blown sand (as you can probably see below) that made the original idea so exciting.


So now it’s back to the drawing board to work out a better way to deal with this.

For the record the C# script is just this …

//Code generated by Grasshopper(R) (except for RunScript() content and Additional content)
 //Copyright (C) 2013 - Robert McNeel & Associates
 public class Script_Instance : GH_ScriptInstance //IGH_ScriptInstance
 #region Members
 /// <summary>List of error messages. Do not modify this list directly.</summary>
 private List<string> __err = new List<string>();

/// <summary>List of print messages. Do not modify this list directly, use the Print() and Reflect() functions instead.</summary>
 private List<string> __out = new List<string>();

/// <summary>Represents the current Rhino document.</summary>
 private RhinoDoc doc = RhinoDoc.ActiveDoc;

/// <summary>Represents the Script component which maintains this script.</summary>
 private IGH_ActiveObject owner;

/// <summary>Represents the number of times that RunScript has been called within this solution.</summary
 private int runCount;

#region Utility functions
 /// <summary>Print a String to the [Out] Parameter of the Script component.</summary>
 /// <param name="text">String to print.</param>
 private void Print(string text)

/// <summary>Print a formatted String to the [Out] Parameter of the Script component.</summary>
 /// <param name="format">String format.</param>
 /// <param name="args">Formatting parameters.</param>
 private void Print(string format, params object[] args)
 __out.Add(string.Format(format, args));

/// <summary>Print useful information about an object instance to the [Out] Parameter of the Script component. </summary>
 /// <param name="obj">Object instance to parse.</param>
 private void Reflect(object obj)

/// <summary>Print the signatures of all the overloads of a specific method to the [Out] Parameter of the Script component. </summary>
 /// <param name="obj">Object instance to parse.</param>
 private void Reflect(object obj, string method_name)
 __out.Add(GH_ScriptComponentUtilities.ReflectType_CS(obj, method_name));

/// <summary>
 /// This procedure contains the user code. Input parameters are provided as regular arguments,
 /// Output parameters as ref arguments. You don't have to assign output parameters,
 /// they will be null by default.
 /// </summary>
 private void RunScript(object x, object y, object a1, object f1, object a2, object f2, object spacing, object mult, object grad, ref object A)

double myX = Convert.ToDouble(x.ToString());
 double myY = Convert.ToDouble(y.ToString());
 double mySpacing = Convert.ToDouble(spacing.ToString());
 double myA1 = Convert.ToDouble(a1.ToString());
 double myF1 = Convert.ToDouble(f1.ToString());
 double myA2 = Convert.ToDouble(a2.ToString());
 double myF2 = Convert.ToDouble(f2.ToString());
 double myMult = Convert.ToDouble(mult.ToString());
 double myGrad = Convert.ToDouble(grad.ToString());

double leng = myY - myA1 * Math.Sin(myX / mySpacing / 100 * myF1) - myA1 * Math.Sin(Math.Sqrt(myX * myX + myY * myY * myGrad) / mySpacing / 100 * myF1 * myMult);

double zVal = myA2 * Math.Sin(leng / mySpacing / 100 * myF2);

A = zVal;

//<Custom additional code>

//</Custom additional code>




Leave a Reply

%d bloggers like this: