Optimizing Grasshopper Definitions Explained!
Part 1 of our video tutorial on this topic. Make sure to check out our channel for more content!
This post below was taken directly from our website's Documentation section. To read the original post click here.
Grasshopper offers hundreds of solutions for any kind of geometrical problem you can think of. Some of them can save us tons of frustration and time when programming our definitions. However, these time savers can be our worst enemy when it comes to processing efficiency.
When uploading a definition to ShapeDiver, computation time matters. Not only is it a precious limited resource within our system, your end users won't wait forever for changes on your online models to happen.
In this blog post we will analyze up to 6 different cases in which "time savers" actually play against you when running your Grasshopper definitions online and what you can do about it instead:
Loft, Sweep and Rules Surface
Case 1: Solid Operations Components
The Solid Intersection, Solid Union, Solid Difference and other components of the same family are widely used for computing the resulting geometry when two or more objects intersect. However, they consume a lot of processing time that can be saved by using mathematical equations.
Let’s say you require to get the wall under a sloped roof:
One option would be to split the wall with the roof plane (Case A). Another option would be to calculate the wall shape by using simple trigonometry (Case B).
Case A and Case B generate the same final result by using different methods.
Case A is using inefficient components such as Split Brep and Mesh Brep which, as you can see in the Bottleneck Navigator below, consume the 54 and 11 percent of the computation time. On the other hand, Case B computes the position of each point in the wall by using simple mathematics. Then it generates the final mesh with the boundary of the wall shape.
In this case, the Bottleneck Navigator shows that the PolyLine and the C# components consume just a 4 and 3 percent of the computation time.
Boundary Polyline to Mesh:To create a mesh from a boundary closed polyline with C#, the command that needs to be called can be found in the RhinoCommon API.
Additionally, if you'd need to use the face of the house to define doors and windows positions, you could easily reuse the calculated values in Case B instead of using components such as Deconstruct Brep to extract the values from the final geometry, which can be very unstable in the long term.
Case 2: Deconstruct Brep
There are Grasshopper developers who prefer creating solid geometries and deconstruct them to make further modifications with its parts (Faces, Vertices, Edges).
Unfortunately, this is not the most stable solution as it depends on the list order that the Deconstruct Brep component gives to its outputs. Any changes made before the Deconstruct Brep will affect the list order of the outputs and therefore any part selection by index number becomes unreliable. For example, if a change was meant to be done in Face no. 3 of the list, this Face may not be the same if the brep to be deconstructed gets affected.
Additionally, after ShapeDiver was upgraded from Rhino 5 to Rhino 6, we could see how the list orders were changed in the core of Grasshopper. Therefore, lots of definitions using unreliable methods like Deconstruct Brep, had to be remade.
The alternative to this method is to build each part of the required design independently using the help of mathematical equations. Deconstruct Brep could be also used if geometrical checks are made afterwards to ensure that the selected part is the required one. However, just the fact of deconstructing a brep consumes more computational time than building its parts independently.
On the other hand, building each part independently could create very long and difficult to understand definitions. That is why it is important to use the power of data lists and trees to keep the definitions compressed and organized, like shown in Case C below.
Use data lists to keep definitions organized.
Case 3: Loft, Sweep and Ruled Surface
These are components difficult to avoid especially if you are creating organic shapes. Unfortunately, they generate a lot of mesh faces as they are not created in a very optimal way. An alternative to them is using the Boundary Surface component if your surface is planar. You can also use a C# script created by us which generates a mesh between a set of polylines in a very efficient way. You just have to make sure that all polylines contain the same amount of vertices.
The mesh that was created with the Loft component contains 952 faces while the mesh created with the C# script contains just 120 faces.
You could also play with the Mesh Brep settings to create a better optimized mesh from the Loft. Just be aware that this component still uses more computational time than the C# as the Bottleneck Navigator shows.
The positive side of the Loft component or similar is that they generate precise smooth shapes. Therefore, if you consider that these components won't greatly affect the performance of your definition and that having precise shapes is essential for your design, making use of them makes no harm.
Download This Example: You can download the Grasshopper definition of this example here and use our LoftMesh C# script to optimize your models.
Case 4: Offset Curve
This component is not really inefficient, but we have created an improved version called PolylineOffset. It lets you experiment with more options in order to have more control over the final result. Its inputs are the following:
Polyline: Planar Polyline to Offset.
Distance as List: You can set a different distance for each edge that constructs the polyline.
Plane: Optional curve plane to use.
Absolute Tolerance: Optional absolute tolerance to use.
Angle Tolerance: Optional angle tolerance to use.
Keep Duplicates: If true, the vertices of edges that get to zero length due to the offset wont be deleted but kept together in the same location. This is ideal if you use this component with our LoftMesh C# as this will make sure that all the offsetted polylines will have the same amount of vertices.
Avoid Self Intersection: If true, the offsetted polyline will be split into pieces to avoid self intersection. In comparison to the native grasshopper Offset component, our component doesn't delete the self intersected sections of the polyline but keep them in case you need them for further processing.
Let's say you want to create a building with different offsets in each floor to have an interesting facade. With our offset component you can input the polyline of the base floor plan shape and then a list of numbers for each edge in the polyline. If your polyline is an octagon, then you will give 8 numbers and the component will offset each side independently.
In the example above, we explode the base polyline to count the amount of edges, and then randomly generate such amount of numbers for each floor. However, the numbers can be set based on a design pattern to end up with more defined shapes. Finally, we use our Loft Mesh C# script described in the previous section to join all the polylines with a single mesh.
Case 5: Mesh Edges
If you require to get the edges of a mesh, the Mesh Edges component is the native solution of Grasshopper. Unfortunately, this component outputs all lines independently and when joining them to get closed polylines, the computational time grows considerably.
If you just require the closed polylines generated by the naked edges of a mesh, we have created a C# script that will remove singular vertices from the mesh and get the closed polylines directly.
Having this mesh, we can get the naked polyline for further processing either by using the native Mesh Edges and Join Curves components, which take the 1 and 89 percent of the computational time, or with our C# script, which just needs the 2% of computational time as the Bottleneck Navigator shows.
Download This Example: You can download the Grasshopper definition of this example here and use our MeshNakedEdges C# script to optimize your models.
Case 6: Transformations
If you have geometry that is identical all around the scene which changes because of its transformations (scaling, moving, rotating, etc.), sending all those identical meshes will make your definition slow.
The solution is to just send one base mesh and apply transformations in the ShapeDiver viewer itself. To do so we have created a C# script that you can use in Grasshopper which will attach transformations to your geometry and send it as metadata to the ShapeDiver viewer.
How do you know how the final result will look like?
Our ShapeDiverDisplayGeometry component is able to read this metadata and show in the Rhinoceros viewport the final result.
In the example above, we have a set of 3 boxes which were created with two different methods. The first method uses our script and sends to the viewer a single box with attached transformations.
On the other hand, the second method applies the transformations directly in Grasshopper by using the native Transform component. This creates triple the amount of geometry that will need to be processed by the ShapeDiver viewer.
Boxes are a very light geometry but if you have organic shapes with thousands of faces, this script will save enormous amounts of computing time in your definition.
Download This Example: Download the Grasshopper definition of this example here and use our Transformations C# script to optimize your models.
While there's definitely a sense of relief in knowing that there's more than one way to solve any given problem on Grasshopper, if your goal is to share this definition with someone else via ShapeDiver, it's important to understand what makes a definition efficient.
Do you want us to share more blog post about this optimization topic? Let us know by leaving a message directly in our Forum! Also, make sure to visit the Documentation section of our website. Here we give you even more information which will hopefully allow you to enjoy ShapeDiver even more.