Using Logic to Guide Your Models in Computational Design
This article is part of the Designing with Numbers series, a continuation of the Geometry Basics series. Together, they explore how computational design is shaped first by geometry, then by numbers.
Part 1 : It’s not always about geometry, numbers matter too.
Part 2 : How Curve Parameters Give You More Control in Grasshopper
Part 3 : How Surface Parameters Turn Geometry Into Information
Part 5 : Using Logic to Guide Your Models in Computational Design (this article)
Most of us know what an if statement is, even if we’ve never called it that. It’s just a simple decision based on some conditions:
If the trains aren’t working, I’ll take the bus.
If they don’t have chicken, get the fish.
If it’s sunny, let’s go to the beach. If not, let’s go rock climbing.
Okay, that last one is a lie. I don’t go to beaches or rock climbing.
We make decisions like this everyday, most of the time without thinking twice. But in computational design, the same idea is trickier. Because instead of deciding on real world things (like taking a walk), we have to make a decision on something abstract (whether to split a curve). It’s harder to understand what it is we are actually deciding on.
An “if” statement is part of what is called logical operations. Which are tasks that require human logic to move forward. These are tasks that the computer cannot do because it normally relates to a condition of the problem.
That’s what today’s article is about. How to use logical operations in computational design. I’ll walk you through how I use them, why they’re one of the most useful ways to manage data and geometry, and I’ll even show you a few ways I used them in Grasshopper.
Why logical operations are so useful
It’s because these operations can help you organize data based on it’s properties. This may sound small but the ability to filter, sort and merge your data is a very useful skill. Even though logical operations itself (do this, if this happens) is straight forward, a lot of how you use them is about finding the right property.
For example:
You can separate the horizontal from the vertical curves with a dot product
You can remove nulls or any other invalid data from your list by cleaning it
You can filter all the geometry from a level based on it’s elevation
It might sound vague now, but this is the foundation of cleaner and robust scripts. Using logical operations like these let’s you treat your data based on what you can get from them. Hopefully by the end of this article, you get a better sense on how you can use logical operators.
Filtering
The simplest use case is filtering. It’s removing things that don’t meet a certain condition. You’re basically saying “if X is true, remove it”. You can do this in Grasshopper using the cull pattern component.
The component takes in a boolean (a true or false) which you can get by testing your geometry. Testing means that you’re checking if a certain property meets a condition like I am testing if my volume is less than 10,000 in the script above.
And you can use this in many ways. One other things often do is to pair it with the closest point component to get rid of any geometry that is too far. Here, in the concept of testing, I’m checking if the points are a certain distance away.
Note: Be careful when you’re filtering by any number because if your problem changes for whatever reason, you need to remember to update the number because it may break your script.
Try to use a dynamic number like a percentage of something, that will always be more stable that an absolute number.
If you’ve used Grasshopper before, filtering is actually straightforward. What makes it powerful is knowing and finding for which property to filter by.
For surfaces you might use it’s normals, areas, or volumes. For curves, that might it’s length, tangents, or curvature. The idea here is to know which properties serve the current problem you’re solving, that’s why I emphasized understanding what you’re working with in the geometry basics series.
The more you work on it, the more you’ll start spotting useful properties instinctively. Especially, if you keep on working with a diverse set of geometry and data.
As a more “complicated” example, you can filter out a list of points by it’s distance to a plane.
I often do this to separate out geometry that are on different elevations. It shows that sometimes, you have to find these properties yourself, like how I needed to check it’s distance to the plane.
The idea is to understand what properties you’re working with. They can come natively with the geometry like tangents for curves. Or, you have to hunt for them like finding the distance of the point from a plane.
And once you understand that, filtering your geometry becomes much easier.
Routing
Routing uses a list of booleans to split the flow of data. You’re saying “if X is true, put it in stream A, if not, put it in stream B”.
It’s the same concept as filtering except we can treat the data separately depending on our test condition. In Grasshopper, we can do this using the dispatch component.
It’s similar to the cull component but you get both the true and false outputs. You can technically use the dispatch component and just use the List A output, it will give you the same as the cull component.
Note: If the order of the input list was important, then ensure you graft your inputs before the component because this will mess up the order of your list since it puts all the trues and falses into their own respective lists.
The other way to split your data is with the unweave component which is similar to dispatch but it uses a pattern instead. A pattern here means you don’t have to feed it the exact number of booleans for the component to work. Grasshopper will apply the pattern to it.
I find this useful when I want to split my data without any properties (e.g. putting every second item in it’s own list). I tend to use this component a lot when creating trusses.
Merging
Once you’ve split things, you’ll often want to recombine them. Just so, you only have one stream of data to work with later.
The weave component in Grasshopper lets you do this. It let’s you bring two separated streams of data back into a list via a pattern. You can actually use the same pattern we used in unweave before.
Note : This is actually how I create the trusses too. I weave them, then unweave them and only take the first output.
A common workflow that I normally do is:
Split a single stream of data into two by testing for some condition
Using a pattern, checking it’s volume, using a dot product, etc.
I’ll then process the two streams separately
Then, combine them again using the same condition with either the unweave or merge component
Another way to merge two streams of data is with the Pick N Choose component which will combine your items based on a true or false input. Unlike the weave component, this will actually choose which item based on the boolean you give it. I do this to ensure my vectors point a certain way.
Using the Pick N Choose, you’re strategically omitting data based on a test that you’ve ran. For me, I tested if my curve was above the plane, I wanted my vectors to point down and if not, it should point up. So, I can test for that and then use the Pick N Choose component to select the right vector.
Beyond pure logic
Once you’re comfortable with using logical operations this way. You can start combining the other techniques we’ve seen in the past (and some we haven’t) to help you organize and control your data more effectively.
These are some the common ways I currently use logical operations together with other techniques in Grasshopper. There is definitely more but I don’t remember them, I will add them below as I come across again.
Merging shatter results
One of the techniques I find myself using the most is merging the results after a shatter.
If you pass an invalid parameter or an empty curve, the component won’t return anything. This makes it harder to carry a list of curves downstream. So one way to to fix this, is to merge the negative tree paths from the shatter.
It’s a more advanced way of using logical operations since it involves data trees but the concept is the same. The property I’m testing for is whether my treebranch is empty after the shatter then I split by it and merge it back later.
Sifting to create alternating values
I sometimes use the sift component to create lists of alternating values. I normally do this for vectors to offset geometry either “inwards” or “outwards”.
The whole reason for this, is that I can have my geometry created in a consistent manner (lines from go from bottom to top) but have my vectors alternating depending on what I need to create.
Final Thoughts
Logical operations might seem trivial, but they’re some of the most versatile tools you’ll use. They let you filter, route, and merge data in ways that keep your scripts clean and reliable. They also let you be more intentional with what you do on your script.
But the key is to know what you’re working with. The better you understand your geometry or data’s properties, the more control you have.
If you’re new to this, start small, filter out nulls, separate curves from lines, re-route breps based on their volumes. But keep striving to understand more about what you’re working with. Over time, you’ll start seeing opportunities everywhere that will help you do more advanced operations in computational design.
Thank you for reading. Consider subscribing if you haven’t, it really helps me know my writing here is useful.