In this tutorial, we will continue with the basics of Grasshopper and create
another space frame, for which the *National Aquatics Center* will serve as
inspiration. The center was built for the 2008 Olympic Summer Games in Bejing,
China, and was nicknamed the *Water Cube* because of its iconic appearance.

The structural design of the *Water Cube* is derived from the structure of foam
or, to be more precise, from an idealized representation of foam: the
Weaire-Phelan
structure. This
model describes the idealized distribution of equal-sized bubbles within a soap
film. The bubbles strive to minimize their surface area per volume and thus to
have the smallest possible surface tension.

As you can see on the pictures below, the steel members of the space frame are
arranged along the edges of the intersections between the bubbles. Between them,
to cover the bubbles, there are ETFE cushions, which are also used
to collect passive solar energy. The *National Aquatics Center* was design and
built by a consortium of PTW
Architects,
Arup, CSCEC and
CCDI. ^{}^{}See Wikipedia entry for
Beijing National Aquatics
Center.

The key element for the design of the space frame is creating of the foam
structure. For this, we use a three-dimensional Voronoi tessellation, which
follows the same principles as the Voronoi diagram^{}*A RANDOM WEAIRE-PHELAN FOAM*. Retrieved from
researchgate.net.^{}Redenbach, Claudia & Sych,
Tetyana. (2008). *A RANDOM WEAIRE-PHELAN FOAM*. Retrieved from
researchgate.net., but for this tutorial a simple
Voronoi tessellation should be sufficient.

## Grasshopper

To keep calculations easy, we will use smaller dimensions and larger elements for our replica of the Water Cube.

#### 1

##### Define a ground plan

The first thing we do in Grasshopper is to define the volume of our cube. To do
this, we place the component RectangleInputs Plane (P) Rectangle base plane X Size (X) Dimensions of rectangle in plane X direction. Y Size (Y) Dimensions of rectangle in plane Y direction. Radius (R) Rectangle corner fillet radius Outputs Rectangle (R) Rectangle Length (L) Length of rectangle curve **X** and **Y**. But here, we need to provide domains. With these, we define
from where to where, compared to the origin of the construction plane,
the rectangle should spread out.

A domain can be created with the component Construct DomainInputs Domain start (A) Start value of numeric domain Domain end (B) End value of numeric domain Outputs Domain (I) Numeric domain between {A} and {B} **A** and **B** represent the lower and upper limit. We create the
numerical values with two Panel`0`

and the other with
`30`

. A shortcut to create a domain is to write `0 To 30`

directly into a Panel

#### 2

##### Create the outer building volume

To create a volume with the just defined rectangle, we use Box RectangleInputs Rectangle (R) Base rectangle Height (H) Box height Outputs Box (B) Resulting box **R**.
The height at input **H** is again defined as a domain. If we connect a number
instead of a domain (here `10`

), the component will automatically create a
domain from *0* to the provided number; in this case the domain will be `0 To 10`

.

#### 3

##### Create the inner volume

To create a second, smaller volume, we use the component Offset CurveInputs Curve (C) Curve to offset Distance (D) Offset distance Plane (P) Plane for offset operation Corners (C) Corner type flag. Possible values:

none = 0

sharp = 1

round = 2

smooth = 3

chamfer = 4Outputs Curve (C) Resulting offsets **D** and must be
negative, in this example, so the offset will point inwards. The component Box RectangleInputs Rectangle (R) Base rectangle Height (H) Box height Outputs Box (B) Resulting box

#### 4

##### Generate the Voronoi structure

Next, we want to generate a 3D Voronoi diagram between the two volumes. For
this, we need the points around which the cells will be generated. We get them
from creating random points in our larger volume with Populate 3DInputs Region (R) Box that defines the 3D region for point insertion Count (N) Number of points to add Seed (S) Random seed for insertion Points (P) Optional pre-existing population Outputs Population (P) Population of inserted points **R**, which defines the
*region* that will contain the random points. At input **N** we define the
number of points. Bear in mind that a large number increases the calculation
time later on.

Now, the just created points will serve us as input **P** (*Points*) on a Voronoi 3DInputs Points (P) Points for Voronoi diagram Box (B) Optional diagram boundary Outputs Cells (C) Cells of the 3D Voronoi diagram Boundary (B) List of boolean values indicating for each cell whether it is part of the original boundary **B** we connect the larger volume, so that
the Voronoi cells are created within this *Box*.

#### 5

##### Cut the Voronoi cells

After having a look at the cells in Rhino, we notice that they fill the whole
volume, even the inner, smaller one, which is not what we desire. Therefore, we
have to cut the inner volume out of the Voronoi foam. For this we use Solid DifferenceInputs Breps A (A) First Brep set Breps B (B) Second Brep set Outputs Result (R) Difference result **A** and the smaller
volume with input **B**. Now, the components calculates the difference and we
get two lists with Breps.

#### 6

##### Select the desired results

The cutting process worked for all cells that touched the inner volume, but we
still have some isolated, intact cells inside the smaller volume. Let’s
filter them out: For this we determine the center point of each Brep with VolumeInputs Geometry (G) Closed brep or mesh for volume computation Outputs Volume (V) Volume of geometry Centroid (C) Volume centroid of geometry Inputs Brep (B) Brep for inclusion test Point (P) Point for inclusion test Strict (S) If true, then the inclusion is strict Outputs Inside (I) True if point is on the inside of the Brep. **B** and the points with input **P**. At output we
get a list with Boolean variables.

Now, we use DispatchInputs List (L) List to filter Dispatch pattern (P) Dispatch pattern Outputs List A (A) Dispatch target for True values List B (B) Dispatch target for False values Inputs Breps A (A) First Brep set Breps B (B) Second Brep set Outputs Result (R) Difference result **L** and our list of
Boolean values with input **P** (*Pattern*). ^{}^{}Have a look at Filter lists for more on working with lists.
We receive a list of cells that lie between the two volumes at output
**B**. For these, the check, if they are inside the smaller volume, returned
*False*.

#### 7

##### Extract the structural elements

In the final step, we can bundle the Voronoi cells inside a BrepInputs Brep (B) Base Brep Density (D) Wireframe isocurve density Outputs Wireframe (W) Wireframe curves