Hidden keyboard and search shortcuts in Grasshopper

Keyboard/mouse shortcuts

Ctrl + Alt: Get category and subcategory of component. Want to know where the ‘path’ component lives? Hold Ctrl + Alt, then click on it.

grasshopper-ctrl-alt-shortcut

Keyboard shortcuts

Modify the draw order

The draw order affects which components sit on top of each other visually. It also affects the calculation order.

Ctrl+B: send component to back of draw order (and will be calculated first)
Ctrl+F: send component to front of draw order (and will be calculated later)

Grasshopper draw order shown by two panels

Search bar shortcuts

Create a number slider

3 3-slider A slider from 0 to 10 (integers)
300 300-slider A slider from 0 to 10 (2 decimal places)

References

http://www.grasshopper3d.com/forum/topics/what-hotkeys-and-shortcuts-are-available-in-grasshopper

Grasshopper: Get intersection points between a list of lines with C#

The following code will produce a list of points that correspond with the intersection points between an assorted list of lines.

It is written for the C# component in Grasshopper, but can be adapted to a compiled component if desired.

Note the check that 0<a<1 and 0<b<1. This represents the requirement that we want intersections to occur along the length of the line, otherwise we aren’t interested in them. If we are also interested in implied intersections (i.e. where we imagine each line continues to infinity in both directions) then we can discard this ‘if’ statement.

And a note to my future self, this code worked on quick tests but was buggy on a real project, so the code below is for reference only!

  private void RunScript(List<Line> x, ref object A)
  {

    List<Point3d> rtn_pts = new List<Point3d>();
    for (int i = 0; i < x.Count - 1; i++)
    {
      for (int j = i + 1; j < x.Count; j++)
      {
        double a;
        double b;
        Rhino.Geometry.Intersect.Intersection.LineLine(x[i], x[j], out a, out b);
        if(a >= 0 && a <= 1 && b > 0 && b < 1)
        {
          rtn_pts.Add(new Point3d(x[i].PointAt(a)));
        }
      }
    }

    A = rtn_pts;

  }

Grasshopper: Manipulate the branches of an existing tree with C#

Say you have a datatree in Grasshopper. It has two levels of branches, and each branch of data has a number of items. We want to ‘flip’ the branches around, but leave the lists of data at the end of each branch intact.

As an example, let’s use the following structure:

And here’s what we want it to look like after:

As a param mapper, this action would look like this:

grasshopper-param-mapper

How would we perform this action using the C# code block?

  private void RunScript(DataTree<object> x, object y, ref object A)
  {

    DataTree<object> rtnTree = new DataTree<object>();
    for (int p = 0; p < x.BranchCount; p++)
    {
      int[] pathint = x.Path(p).Indices;
      GH_Path flippath = new GH_Path(new[] {pathint[1],pathint[0]});

      foreach (var item in x.Branch(new[] {pathint[0],pathint[1]}))
      {
        rtnTree.Add(item, flippath);
      }

    }

    A = rtnTree;

Send a command from Grasshopper to Rhino in C#

In Grasshopper, it’s possible to send commands directly from Grasshopper to Rhino. How? By using the C# component.

Simply add the following line to your C# code.

Rhino.RhinoApp.RunScript(string script, bool echo);
//script: The command to send
//echo: Set to true for the command to appear in Rhino's command prompt

For example, if I want to automatically save the Rhino document, I could add the following to a C# component:

Rhino.RhinoApp.RunScript("Save", true);

For more complex commands, we can use some special syntax. For example, if I want to save the file with a custom filename, I can use:

Rhino.RhinoApp.RunScript("_-Save test3.3dm", true);

The hyphen allows us to modify parameters, and the underscore allows us to enter more than one command at once without Rhino waiting for manual user input.

More information

The full list of Rhino commands is available here.

For more detail about using the RunScript method, read this.

Change the colour of the Grasshopper canvas

To change the colour of the Grasshopper canvas, Johannes Braumann very helpfully provided a C# script. However, the script is now out of date with recent builds of Grasshopper, having been published in 2010. Below is an updated, working version.

This script helped me change the colour of the Grasshopper canvas to be white – which has saved me a lot of time in updating images in posts like this.

The component looks like this:

Grasshopper change canvas colour component

Do-it-yourself C# script

Paste the script into a C# component. Take care to set input names and types to match the parameters below. This code is lightly modified from Braumann’s script.

  private void RunScript(bool switcher, Color canvas_back, Color canvas_grid, ref object A)
  {
    if (switcher == true)
    {
      Grasshopper.GUI.Canvas.GH_Skin.canvas_grid = canvas_grid;
      Grasshopper.GUI.Canvas.GH_Skin.canvas_back = canvas_back; 
      Grasshopper.GUI.Canvas.GH_Skin.canvas_edge = Color.FromArgb(255, 0, 0, 0); 
      Grasshopper.GUI.Canvas.GH_Skin.canvas_shade = Color.FromArgb(80, 0, 0, 0); 
    }
    else
    {
      //DEFAULTS
      Grasshopper.GUI.Canvas.GH_Skin.canvas_grid = Color.FromArgb(30, 0, 0, 0);
      Grasshopper.GUI.Canvas.GH_Skin.canvas_back = Color.FromArgb(255, 212, 208, 200); 
      Grasshopper.GUI.Canvas.GH_Skin.canvas_edge = Color.FromArgb(255, 0, 0, 0); 
      Grasshopper.GUI.Canvas.GH_Skin.canvas_shade = Color.FromArgb(80, 0, 0, 0);
    }
  }

Download a ready-made component

If you would rather not play about with the C# component, you can just open this Grasshopper file instead.

Open and run Grasshopper from a batch file

How to automatically open Rhino and run a Grasshopper file using a batch file.

A batch file is a file that allows Windows to run a list of commands automatically. They are simple text files with file extension .bat that you can easily write yourself. This post is a good tutorial on how to make a batch file.

Batch files were used in the Pollination project in Grasshopper to automate Grasshopper tasks between multiple computers. Andrew Heumann explained here how to write the batch file to start Rhino and run a Grasshopper file.

What to write in the Grasshopper batch file

Copy this into a text document, and change the fields to your own file locations. Save the file, and change the extension from .txt to .bat.

@ECHO OFF
cd **PATH TO DIRECTORY CONTAINING GH FILE**
"**PATH TO RHINO.EXE**" /nosplash /runscript="-grasshopper editor load document open **GRASSHOPPER FILE NAME** _enter" "**PATH TO ASSOCIATED RHINO FILE**"

For example, I have a Rhino and a GH file on my desktop, respectively called random.gh and random2.3dm.

@ECHO OFF
cd C:\Users\jrams\Desktop
"C:\Program Files\Rhinoceros 5 (64-bit)\System\rhino.exe" /nosplash /runscript="-grasshopper editor load document open C:\Users\jrams\Desktop\random.gh _enter" "C:\Users\jrams\Desktop\random2.3dm"

Now you can just double-click on the batch file you have made. Rhino should now open with your Grasshopper file.

Seeing an error with the characters ╗┐?

The ECHO OFF command should stop the command prompt from being visible. Sometimes, you might get an error like this. This error stops the first line in your batch file from being executed properly, in this case disabling the ECHO OFF command.

batch file BOM error

Long story short, your text file’s encoding is incompatible with the command prompt. To fix, in Notepad, save with ANSI encoding. Or in Sublime, go to File then Save With Encoding. Choose UTF-8 (NOT UTF-8 with BOM).

Grasshopper: Where is Grasshopper.dll and GH_IO.dll?

When developing Grasshopper components, we need to make reference to two Grasshopper Dlls: Grasshopper.dll and GH_IO.dll. These provide the GH_Component class, which custom components inherit from, as well as providing other useful Grasshopper functions.

Grasshopper.dll and GH_IO.dll

The exact location depends upon your particular Rhino installation. On my computer, I found them buried within the AppData folder at:

C:\Users\James\AppData\Roaming\McNeel\Rhinoceros\5.0\Plug-ins\Grasshopper {...}\0.9.76.0

Within this folder, I found a large collection of files, including Grasshopper.dll and GH_IO.dll.

A similar path may exist on your computer. If you can’t find anything like it on yours, you can look up the folder through Rhino: (from David Rutten)

  1. Start Rhino
  2. Run the _PluginManager command
  3. Locate Grasshopper in the list of plugins
  4. Open the properties for the Grasshopper plugin
  5. At the bottom of the Properties window there’s a ‘File name’ entry
  6. This points to GrasshopperPlugin.rhp, which is sitting next to Grasshopper.dll

You may need to widen the window to see the full path.

Grasshopper DLL path

Grasshopper: Map a path using C#

The Path Mapper is a component that allows you to map data to different branches. It is also possible to replicate this behaviour entirely in C#.

The following code maps object x to path address 0, 0, 5. See this post for a simple overview on data trees in Grasshopper.

‘DataTree’ is the class made specifically for the C# component to handle data trees. (If you’re programming in Visual Studio, it’s better to use GH_Structure.) We use a different class, GH_Path, as the tool to define the path structure.

C# code

  private void RunScript(object x, object y, ref object A)
  {

    int[] address = {0, 0, 5};
    var pth = new GH_Path(address);
    var tree = new DataTree<object>();

    tree.Add(x, pth);
    A = tree;

  }

Grasshopper example: Glare using Radiance/Honeybee

A simple example of how to set up a glare analysis using Honeybee, an interface for providing Radiance daylight analysis in Grasshopper.

Grasshopper canvas for Honeybee glare analysis

Download


Images

Grasshopper shoebox example for glare analysis

The simple building used for analysis

glare example Grasshopper Radiance

Using EmbryoViz to visualise how a user would perceive daylight and glare inside the building

Grasshopper: automatically create a value list in C#

Another example on how to automatically create a value list in Grasshopper using the C# component.

This file is mostly for personal reference, but there are snippets in here that you may find useful. I designed this component to read a text file containing XML-like data, save the data in a class structure, and then filter the data. The filtering is done by a drop-down list that is automatically added by the component, and is pre-populated with valid options.

Useful code includes:

  • How to create a value list with C# code
  • How to populate the value list
  • How to create and use a DataTree in the C# component

C# code

This code is designed for the C# component in Grasshopper.

private void RunScript(List<string> x, int y, ref object params_, ref object results_)
  {

    var models = new List<Model>();

    //parse input text
    for (int i = 0; i < x.Count; i += (valuecount + 2))
    {
      var model = new Model();
      model.Params = FormatParamString(x[i]); //convert CSV to list of doubles
      for (int j = i + 1; j < i + 4; j++)
      {
        var item = new DictItem();
        FormatModelLine(x[j], out item.Name, out item.Value);
        model.Results.Add(item);
      }
      models.Add(model);
    }
    Component.Message = models.Count.ToString() + " models";

    AnalysisTypes = CalcUniqueAnalyses(models);

    //make dropdown box
    if(Component.Params.Input[1].SourceCount == 0 && Component.Params.Input[0].SourceCount > 0)
    {
      var vallist = new Grasshopper.Kernel.Special.GH_ValueList();
      vallist.CreateAttributes();
      vallist.Name = "Analysis types";
      vallist.NickName = "Analysis:";
      vallist.ListMode = Grasshopper.Kernel.Special.GH_ValueListMode.DropDown;

      int inputcount = this.Component.Params.Input[1].SourceCount;
      vallist.Attributes.Pivot = new PointF((float) this.Component.Attributes.DocObject.Attributes.Bounds.Left - vallist.Attributes.Bounds.Width - 30, (float) this.Component.Params.Input[1].Attributes.Bounds.Y + inputcount * 30);

      vallist.ListItems.Clear();

      for(int i = 0; i < AnalysisTypes.Count; i++)
      {
        vallist.ListItems.Add(new Grasshopper.Kernel.Special.GH_ValueListItem(AnalysisTypes[i], i.ToString()));
      }
      vallist.Description = AnalysisTypes.Count.ToString() + " analyses were found in the SBA file.";

      GrasshopperDocument.AddObject(vallist, false);

      this.Component.Params.Input[1].AddSource(vallist);
      vallist.ExpireSolution(true);
    }

    //we now have our results in a nice classy format. let's convert them to a datatree
    var resultsvals = new DataTree<double>();
    var paramvals = new DataTree<double>();
    string astr = AnalysisTypes[y];

    Component.Params.Output[1].VolatileData.Clear(); //bug fix for when new dropdown is made
    Component.Params.Output[2].VolatileData.Clear(); //bug fix for when new dropdown is made

    for (int i = 0; i < models.Count; i++)
    {
      var pth = new GH_Path(i);
      foreach (var result in models[i].Results)
      {
        if(astr == result.Name)
        {
          resultsvals.Add(result.Value, pth);
          foreach(var param in models[i].Params)
          {
            paramvals.Add(param, pth);
          }
        }
      }
    }
    results_ = resultsvals;
    params_ = paramvals;




  }

  // <Custom additional code> 

  int valuecount = 3;
  List<string> AnalysisTypes = new List<string>();

  public class DictItem
  {
    public DictItem()
    {
    }

    public string Name;
    public double Value;
  }

  public class Model
  {
    public Model()
    {
    }

    public List<double> Params = new List<double>();
    public List<DictItem> Results = new List<DictItem>();

    public List<string> ToListString()
    {
      var rtnlist = new List<string>();
      foreach (var result in Results) rtnlist.Add(result.Name + ", " + result.Value.ToString());
      return rtnlist;
    }

  }

  List<double> FormatParamString(string input)
  {
    var rtnlist = new List<double>();


    input = input.Replace("<", "");
    input = input.Replace(">", "");
    input = input.Replace('m', '-');
    input = input.Replace('_', '.');
    string[] splitstring = input.Split('c');
    foreach(string str in splitstring)
    {
      try
      {
        rtnlist.Add(Convert.ToDouble(str));
      }
      catch
      {
        rtnlist.Add(0);
      }
    }
    return rtnlist;
  }

  /// <summary>
  /// Get name and value of analysis from an SBA string
  /// </summary>
  /// <param name="input"></param>
  /// <param name="name"></param>
  /// <param name="val"></param>
  /// <returns></returns>
  void FormatModelLine(string input, out string name, out double val)
  {
    int firstopen = input.IndexOf('<');
    int firstclose = input.IndexOf('>');
    int lastopen = input.LastIndexOf('<');

    name = input.Substring(firstopen + 1, firstclose - firstopen - 1);
    val = Convert.ToDouble(input.Substring(firstclose + 1, lastopen - firstclose - 1));
  }


  /// <summary>
  /// Get analysis types from list of models
  /// </summary>
  /// <param name="models"></param>
  /// <returns></returns>
  List<string> CalcUniqueAnalyses(List<Model> models)
  {
    List<string> rtnlist = new List<string>();
    foreach (var model in models)
    {
      foreach (var result in model.Results)
      {
        bool found = false;
        foreach (var calc in rtnlist)
        {
          if(calc == result.Name) found = true;
        }
        if(!found) rtnlist.Add(result.Name);
      }
    }
    return rtnlist;
  }