With the arrival of Code Blocks in Dynamo version 0.7.0 and later, there are now at least four distinct options for calculating stuff:
- Traditional nodes
- The Formula node
- Code Blocks
(There’s a fifth method, too, if you write your own node, compile it, and import the dll using zero-touch import—look for a future blog post!) And any of these methods could be wrapped in a custom node. The point is, there’s now a lot going on in Dynamo. This blog post is meant to serve as a Rosetta Stone: how to calculate stuff different ways.
For purposes of making the comparison clear, I’ve chosen to generate the same cool surface from a grid of points whose z-coordinate I will spend the rest of this blog entry calculating. The surface is a solution to this equation (A and c are constants):
With this and other example images in this post, click the image to see the full graph that makes the surface. Download the .dyn file with all four examples at the bottom.
Everybody loves using traditional nodes. But using them may not always be the best solution. The image above shows one possible arrangement of traditional nodes that solves the surface equation. The graph might look familiar and comfortable to the person who made it, but it might not be obvious to others what it does unless it’s well-labeled. Having clear logic in your graph helps your future-self and coworkers decode what your present-self was thinking. This is especially true when dealing with math-heavy operations, when there is no geometry to preview to help you figure out what’s going on.
Dynamo version 0.7.0 and later uses degrees for angles. You may note the use of the node Math.RadiansToDegrees because formulas such as this expect angles in radians.
For more information on the Formula node and its syntax, see the post NCalc and Dynamo’s Formula node. The Formula node has clear advantages for working with math-heavy operations, and its syntax will be familiar to anyone who has ever used a graphing scientific calculator.
The Formula node, which uses an external library of functions, expects angles in radians. Documentation for the NCalc project‘s syntax can be found at:
|Operators:||=, &&, *, /, +, %,…||NCalc operators|
|Values:||1.22e1, true, .1e-2,…||NCalc values|
|Functions:||log(), sin(), round(),…||NCalc functions|
Python is a powerful tool, relatively unlimited in its capabilities. But you have to know Python. And burying your code in a Python node is as close to making a “black box,” where everything is obscured, as you can get. Check out this blog post for more information on the Python node.
Double-click a Python node to see its innards. Inside this one, you’ll see:
You’ll notice some boiler-plate text at the top, which is meant to help you reference the libraries you’ll need. To the standard text, I’ve added a statement to import the math library. Inputs are stored in the IN array. When extracting the inputs from IN, I just have to keep track of the order in which I attached the inputs. Values are returned to Dynamo by assigning them to the OUT variable.
To solve the equation for a grid of points, I will have just one value for the constant amp and one value for the constant c, but I will have a potentially long list of x– and y-values. With Python, which operates outside the cozy context of Dynamo, you will have to be explicit about what you’re working with: single-values or lists of values. I’ve used a for loop to parse through the list of x-values, finding one new z-value for each. The code I’ve written is less robust than the three other methods. I have assumed, for instance, that I will have at least as many y-values as x-values. And I’ve assumed that amp and c inputs will be single values. The code might break and return an unfriendly error message rather than a nice list of z-values if my co-worker hooks up the inputs wrong. There is no automatic lacing here like in Dynamo. Of course, you can make this Python code just as robust as anything else by adding in checks or by generalizing the logic that solves the equation, but I will leave that as an exercise for the reader. My point is: no one is holding your hand in Python land. For solving math problems, there are usually better ways.
Code Blocks are magic. And in case you haven’t noticed yet, I have a clear bias toward them. Especially for math. Note that I have used the function Math.RadiansToDegrees() just as I had to for the traditional nodes solution because Dynamo expects angles in degrees.
With a Code Block, you can call any other node in Dynamo. Imagine all of the advantages of the traditional node-based method together with a clear, concise, easy-to-understand and easy to change block. Read more in the post [Scratching the Surface of] Everything You Need To Know About Code Blocks.
For a moment, forget how you would solve this with nodes, calculators, or code. If your teacher assigned this problem as homework and you had to work out the answer on paper, how would you do it? Here’s the problem:
I’ve graded enough homework assignments to know that there are an infinite number of ways to solve even the simplest problem, and some are even correct. Among the myriad possibilities, here’s one.
Notice that I’ve structured my solution with a Code Block the same way. And when you change your single x– and y-value to a series of points, it just works. If you handed me your Dynamo definition and asked me to fix something, I would much rather try to figure out what you did if I could read Code Blocks!
For kicks, check out the similarity between the Python code—specifically the part that matters—and the Code Block.
Code Blocks give you a lot of the power of Python without all the other stuff.
So, which method do you like best? Download the sample file MathTransit.dyn.
Making it real
Once I have a surface in Dynamo, I can use it as a scaffolding to place panels in Revit.
With this logic tacked on to the end of the surface, I use a custom node from the Package Manager called UV Quads on Surface to create a grid and organize points into groups of 4 describing each cell in the grid. I use those points to place an adaptive component. I use a reporting parameter in the adaptive components that describes the amount of deflection—by how much the panel is out-of-plane—and I use those numbers to pick from a color range from blue to red. Then I use that information to color the components, in Revit, according to their planarity.