Chapter 2: Introduction to Data Structures

All algorithms involve processing input data to generate a new set of data as output. Data is stored in well-defined structures to help access and manipulate efficiently. Understanding these structures is the key for successful algorithmic designs. This chapter includes an in-depth review of the basic data structures in Grasshopper.

2.1 Overview

Overview of data structures in Grasshopper

Grasshopper has three distinct data structures: single item, list of items and tree of items. GH components execute differently based on input data structures, and hence it is essential to be fully aware of the data structure before using. There are tools in GH to help identify the data structure. Those are Panel and Param Viewer.

Figure(34): Data structures in Grasshopper

Processes in GH execute differently based on the data structure. For example, the Mass Addition component adds all the numbers in a list and produces a single number, but when operating on a tree, it produces a list of numbers representing the sum of each branch.

Figure(35): Components execute differently based on the data structures. Result of adding numbers from Figure(34)

The wires connecting the data with components in GH offer additional visual reference to the data structure. The wire from a single item is a simple line, while the wire connecting a list is drawn as a double line. A wire output from a tree data structure is a dashed double line. This is very useful to quickly identify the structure of your data.

Display the data structure Example
Item: single branch with single item
Wire display: single line
List: single branch with multiple items
Wire display: double line
Tree: multiple branches with any number of items per branch
Wire display: double dashed line

2.2 Generating lists

Generate lists in Grasshopper

There are many ways to generate lists of data in GH. So far we have seen how to directly embed a list of values inside a parameter or a panel (with multiline data). There are also special components to generate lists. For example, to generate a list of numbers, there are three key components: Range, Series and Random. Lists can be the output of some components such as Divide curve (the output includes lists of points, tangents and parameters). Use the Panel component to preview the values in a list and Parameter Viewer to examine the data structures.

The Range component creates equally spaced range of numbers between a min and max values (called domain) and a number of steps (the number of values in the resulting list is equal to the number of steps plus one).
Figure(36): Generate a list of 8 numbers using the Range component in Grasshopper
The Series component also creates an equally spaced list of numbers, but here you set the starting number, step size and number of elements.
Figure(37): Generate a list of 7 numbers using the Series component in Grasshopper
The Random component is used to create random numbers using a domain and a number of elements. If you use the same seed, then you always get the same set of random numbers.
Figure(38): Generate a list of numbers using the Random component in Grasshopper
The Divide component outputs divide points, tangents and parameters on curve.
Figure(39): Divide Curve takes a single input (curve) and generate lists of output
Tutorial: 2_2_1 Generating lists
Explore 4 different ways to create circles. Use different data sources and data structures.
Solution...

1. Directly set a circle in a parameter
2. Set the plane input to the default XY-Plane (internal). Supply a list of radiuses using Range component
3. Supply one value for the center. Normal is set to default (internal) List of radiuses using Random component
4. Create a circle from 3 points:
A: set internally to one value
B: Supply one value
C: Supply a list of values using the Series component to set a list of Z coordinates

2.3 List operations

Generate lists in Grasshopper

Grasshopper offers an extensive list of components for list operations and list management. We will review the most commonly used ones.

You can check the length of a list using the List Length component, and access items at specific indices using the List Item component.
Figure(40): Examples of list operations in Grasshopper
Lists can be reversed using the Reverse List component, and sorted using the Sort List component.
Figure(41): Lists can be reversed or sorted using designated components in Grasshopper
Components such as Cull Patterns and Dispatch allow selecting a subset of the list, or splitting the list based on a pattern.These components are very commonly used to control data flow and select a subset of the data.
Figure(42): Cull part of a list using components such as Cull Pattern and Dispatch
The Shift List component allows shifting a list by any number of steps. That helps align multiple lists to match in a particular order.
Figure(43): Shift operation in Grasshopper
The Subset component is another example to select part of a list based on a range of indices.
Figure(44): Select a subset of the list using a range of indices
Tutorial: 2_3_1 List operations
Given two lists of points from dividing two concentric circles, generate the following patterns:
Solution...
Solution video...

2.4 List matching

Generate lists in Grasshopper

When the input is a single item or has an equal number of elements in a simple list, it is easy to imagine how the data is matched. The matching is based on corresponding indices. Let’s use the Addition component to examine list matching in GH. Note that the same principles apply to all other Grasshopper components.

Figure(45): Examples of primitive data types common to all programming languages

There are times when input has variable length lists. In this case, GH reuses the last item on the shorter list and matches it with the next items in the longer list.

Figure(46): The default list matching in Grasshopper reuses the last element of the shorter list

Grasshopper offers alternative ways of data matching: Long, Short and Cross reference that the user can force to use. The Long matching is the same as the default matching. That is, the last element of the shorter list is repeated to create a matching length.

Figure(47): Long list matching is the default matching mode in Grasshopper

The Short list matching truncates the long list to match the length of the short list. All additional elements are ignored and the resulting list has a length that matches the shorter list.

Figure(48): Short matching of lists omits additional values in longer lists

The Cross Reference matches the first list with each of the elements in the second list. The resulting list has a length equal to the multiplication product of the length of input lists. Cross reference is useful when trying to produce all possible combinations of input data. The order of input affects the order of the result as shown in Figure (49).

Figure(49): Cross reference matching creates longer lists to account for all possible permutations

If none of the matching methods produce the desired result, you can explicitly adjust the lists to match in length based on your requirements. For example, if you like to repeat the shorter list until it matches the length of the longer list, then you’ll need to create the logic to achieve that as in the following example.

Figure(50): Need to create custom script to generate custom matching
Tutorial 2_4_1 List matching
Use the 4-step method to generate an algorithm that takes 6 numbers (0 to 5) and turn them into a cube of points as in the image:
Solution...
Output:
A list of 6x6x6 = 216 points constructed from a list of X, Y, Z coordinates
Key Process:
Use the Construct Point component to generate the list of points
Input:
Examine input using the Parameter Viewer and Panel components.
The given list has 6 points representing each coordinate along each axis
Intermediate processes:
Need to find all possible permutations for the coordinates to create the cube of 216 points along all 3 axes.
Use Cross Reference matching to generate lists of coordinates that have all possible permutations
Putting it all together

2.5 Tutorials: data structures

Tutorial 2.5.1: Variable thickness pipe
Use the 4-step method to create a surface similar to the one in the image:
Solution...
download GH file...
Solution video...

Algorithm Analysis:
We can think of two different ways to generate this surface:
1. Loft circles created along a line at random locations with random radii
2. Create a profile curve at the circles start points, and Revolve around the line

Output:
The surface
Key Process:
Use the Loft component to generate the surface
Input:
Line (not given, so create one),
Number of intervals (not given, assume it is equal 10)
Thickness range (not given, assume it is equal to 1.0 to 3.0)
Intermediate processes #1:
The Loft is created from a list of circles. Use the Circle component that takes centers, normals and radii lists.
Use the default Loft options
Intermediate processes #2:
To create a list of random radii, use the Random component and the input thickness range
Intermediate processes #3:
Evaluate the line at random intervals. Use the Evaluate Curve component to extract center points and normals, and use the Random component to generate the parameters along the curve.

Problem:
The loft follows the order of input curves. however, the parameters (generated from the Random component) are not ordered along the line and hence it produces unordered circles. Use the Sort List component to order the parameters before feeding them into the Evaluate Curve
Putting it all together
Tutorial 2.5.2: Custom list matching
Given the following three lists of numbers: [1, 2], [10, 20, 30] and [0.2, 0.4, 0.6, 0.9, 1], explain the default GH list matching when they are used as input. Compare the default matching with the Grasshopper Shortest List matching. Finally, use the original lists to create custom matching that repeats the pattern in the shorter lists to create a periodic matching until it matches the length of the longest list. For example [1,2] becomes [1,2,1,2,1].
Solution...
download GH file...
Construct default GH matching:
To test the matching, feed the lists into the coordinates of the Construct Point component and observe the result
Analysize GH default matching:
The last element of shorter lists is repeated until all lists have the same length, then elements are matched by indices
Construct shortest List matching:
Omit additional values in longer lists so that the length of all lists equals the length of the shortest list
Create repeated custom matching:
We know that the longest list has 5 items, but it is a good practice to make the script generic so it works with any input. First, figure out the length of the longest list, then use the Repeat component to repeat the elements in shorter lists until they match the length of the longest list
Tutorial 2.5.3: Simple truss
Use the 4-step method to generate a simple truss as in the image. Use the given input for the baseline (base of the truss), height, number of runs (or spans), and the radius of the joint.
Solution...
download GH file...
Solution video...

Algorithm analysis:
Define values for the input:
L= create a Line along X-Axis
H= assume height=7
R= assume number of runs=10
J= assume joint radius=0.5

Divide the baseline into 20 spans (2*R)
Move every other point by 7 units (or H) in the Z-Axis direction
Create 3 sets of ordered points for the beams along the base, top and middle, then connect each of the 3 sets with a polyline. Create spheres to represent the joints.

Solution steps:
Output:
There are 2 outputs, the beams as curves (polylines) and joints as spheres (surfaces)
Key Process:
Need to create the polylines for the top, middle, and bottom beams. Use the Polyline component with a relevant set of points for each.
Use the Sphere component to create joints. Use middle points and joint radius as input.
Input:
Specify the inputs and assume values when they are not given:
line, number of runs, height and joint radius
Intermediate processes #1:
Divide the curve with twice the number of runs. Use Divide Curve component and Multiply the number of runs
Intermediate processes #2:
To create top points, select every other point from the list of all divide points, then move vertically by the height amount.
Use Cull Pattern component to select points and Move component to shift vertically
Intermediate processes #3:
To create bottom points, select every other point, in the invert pattern used to select top points.
Use Cull Pattern component to select points (set the invert flag for the pattern input)
Intermediate processes #4:
To create middle points, Weave the top and bottom points.
Putting it all together
Tutorial 2.5.4: Pearl necklace
Create a necklace with one big pearl in the middle, and gradually smaller size pearls towards the ends as in the image. The number of pearls is between 15-25.
Solution...
download GH file...

Algorithm analysis:
The workflow to create the necklace follows these general lines:
1. Divide the curve into segments of variable distances (widest in the middle and narrow towards the ends)
2. Find length and midpoints of each segment
3. Create spheres at midpoints using half the length as radius


Solution steps:
Output:
The surfaces
Key Process:
Use the Sphere component to generate the pearl surfaces
Input:
Necklace curve,
Number of pearls as a parameter (can be changed by the user)
Intermediate processes #1:
The Range component creates equal distances. We need to change to variable distances and for that we can use the Graph Mapper component to control the spacing.
Intermediate processes #2:
Since we have normalized distances from the start of the curve (parameters are between 0 to 1), we can use the Evaluate Length component to find the divide points.
Intermediate processes #3:
Generate the segments. Use Polyline and Explode components to turn the points into segments
Center points are calculated at the middle of the segments. Use Evaluate Length at mid length
Radii are calculated as half of each segment length. Use Length and Division components
Putting it all together

Next Steps

Those are the introduction to data structures. Next, learn Advanced Data Structures.

This is part 2-3 of the Essential Algorithms and Data Structures for Grasshopper.