Thursday, November 22, 2012

Spiral Point

After today’s very generous mentions in Vasari Talk 22, I thought I’d better finish up another post. This builds on last week’s layout, with a twist!

It’s very easy to use Dynamo to build ‘dumb’ models, by just placing points at exact coordinates. But I’m intrigued by ways of using Dynamo to build proper parametric Revit components: Placing lots of points quickly to generate complex form, while at the same time relating those points together is useful ways. Last week’s post was a first step on that path, and this post takes it a bit further.

So, last week’s post ended by using a ‘Reference Point on Edge’ node to host a point on a curve. This layout hosts a point on that point’s YZ reference plane, so that as the first point moves, the second point is carried along:

Spiral Point Layout

You’ll recognise the arrangement of nodes at the top of the layout from the last post: A pair of reference points connected by a curve (aka straight line), and then a reference point hosted on that curve. The parametric position of the hosted point along the curve is driven by a slider node, and the slider is set to give values between 0 and 1: By moving the slider, the hosted point moves from one end of the curve to the other.

This hosted reference point is fed to a new User node ‘GetCoordinatePlaneReferenceYZ’, which gets the point’s YZ reference plane. The refplane is fed into the ‘face’ input of a ‘Reference Pont on Face’ node, which places a point on the plane. I was surprised that the face input would accept a reference rather than a face, but it’s great that it does.

Now that would be fine, because the plane-hosted point would move with the curve-hosted one, but I was inspired by David Light’s 2010 video of a helical adaptive component to try and make the point move in a helix or spiral, and the set of nodes at the bottom of the layout make that happen.

Helical movement is a combination of moving around in a circle and moving along a line. The slider makes the points move along the line, so I just had to get the plane-hosted point to move in a circle on the plane.

The slider feeds into a multiply node along with the value 2π, and so by moving the slider from 0 to 1, the multiply produces an angle value from 0 to 2π radians. The angle is fed into Sine and Cosine nodes to give Y and Z coordinates, multiplied by the number 20 at the bottom to give a 20 unit radius circle.

The only new User node required was GetCoordinateReferencePlaneYZ, which wraps a snippet of Python that makes the API call:


When run, you get a simple line and two hosted points:

Spiral Point Screenshot

When run automatically, you get to slide the line-hosted point up and down the line, while the plane-hosted point moves in a spiral around it:

Unable to display content. Adobe Flash is required.

It’s just unfortunate that the slider is so small on screen that it makes the movement a bit jerky. But I think the video just about shows the idea.

And here’s the source: Spiral Point

Thursday, November 15, 2012

Curve By Points and Reference Point On Edge

Post-pumpkin, I’ve been exploring the conceptual massing environment in more depth, both through the user interface and via the API. So I thought it would be fun to implement the WikiHelp API examples in Dynamo. This is the first, and follows this WkiHelp example:

WH 14-1a CurveByPoints

The left hand side is not very interesting: Just some hard-coded XYZs, fed into a List node. The list of XYZs is then fed to a Reference Point node to generate a list of reference points (the Reference Point node is one of the few that will equally accept either a single value or a list). And then the refpoints are fed into a Curve By Points node to generate the curve.

The last two nodes generate the hosted point on the curve (described in the WikiHelp text but currently missing from the code listing). The Reference Point On Edge node creates the point and the Number node sets the parametric position of the hosted point along the curve. Replacing the Number node with a slider allows you to move the point along the curve dynamically (with Run Automatically on, and a reasonably fast computer).

WH 14-1a CurveByPoints image

And here’s the source: WH 14-1 Curve By Points

Tuesday, November 6, 2012

Punkinator Dissection

This is a description of how my Dynamo-powered Punkinator works. I’ll start with an overall, top-down description, and then move on to a bottom-up explanation of each of the nodes.

The pumpkin is a loft form generated from a set of profiles. Each profile is a loop of model lines drawn on a horizontal plane, and the loops get smaller towards the top and bottom of the form to produce the generally spherical shape. You can see the purple reference points used to create the loops in this screenshot of a pumpkin in X-Ray View (you can’t see the model lines because the refpoints are so closely spaced):

X-Ray Pumpkin

The reference points are calculated using Johan Gielis’ superformula of an ellipse, equation (2) in his 2003 paper:

Superformula Equation

This looks a bit intimidating, but the aim of it is to calculate a radius (r) from an angle, phi (Φ). Then use the radius and angle as polar coordinates to plot a point. If you plot a series of points using different input angles, you can join the dots to create a loop.

Why use the superformula? Well the sample plots in Gielis’ paper suggested that it could create some nice organic shapes, given the right input parameters a, b, m, n1, n2 and n3. And there are several images online that show pumpkin-like superformula shapes.

So I figured that if I could generate a series of pumpkin-shaped loops using the superformula, I could loft a form through them and create a pumpkin for Zach Kron’s 4th Annual Parametric Pumpkin Carving. And it worked!

Now on to the more detailed explanation, starting at the bottom:


This is the fundamental node. It calculates the radius from a given angle, based on the superformula with input parameters a, b, m, n1, n2 and n3.


It is a fairly straightforward implementation of the superformula. The angle, m, a, and b inputs are at the left; the n1, n2 and n3 inputs are in the middle. The rest is just the mathematical manipulation.

The Superformula node makes use of a couple of helper nodes: Abs, which calculates the absolute value of the input:


and x^y which calculates x to the power y using a snippet of Python:


This is the only bit of Python in the solution. I guess you could make a recursive pure-Dynamo node that would calculate a power. But at the time, the Python implementation was more direct.

Incidentally, this also shows one way of pushing multiple inputs into a Python node: The List node packages the two input values into one list; and then the Python code unpacks the list elements into individual variables.

I put the Transaction node in because while I was testing, Dynamo complained that it needed one. I don’t really see why it should need one at this point, so I may try taking it out again now.

Superformula XYZ

This creates a Revit API XYZ element using the distance and angle from the superformula node:

Superformula XYZ

It also has a scale input, to scale the loop up and down, and a z input, to move the loop to different z values.

Superformula XYZ uses just one helper node, Polar XYZ:

Polar XYZ

This uses a bit of trigonometry to calculate the X and Y values from the input polar coordinate, and then calls the standard XYZ node.

Why do I keep creating these helper nodes? Three reasons:

  1. You can test and debug the helper node in isolation
  2. It makes the main node simpler to understand
  3. You can re-use the helper nodes in other solutions

Superformula Loop

This creates a loop of reference points from the superformula, and then connects them with lines:

Superformula Loop

The nodes at the bottom of the layout divide a full circle into a sequence of angles. The Number node on the left is where you set the number of divisions (i.e. the number of points in the loop). Higher numbers create smoother loops, more slowly.

The upper Map node calls Superformula XYZ once for each angle, and then the Reference Point node and ConnectPoints nodes generate the loop of points and lines. ConnectPoints is a user node that ships with Dynamo.

Superformula Loop uses two helper nodes: 2pi/n, which gives the angle that is 1/nth of a circle:


Dynamo measures angles in radians, and there are 2π radians in a circle (don’t be put off by the radians: They’re just a different way of measuring angles, like degrees but more convenient for some maths).

…And ‘Build Sequence 0 to n’, which builds an integer sequence from 0 to n:

Build Sequence 0 to n

The standard Build Sequence node excludes the end value, and if I used this to generate my loop, it would leave a gap. I need to generate a complete sequence of angles from 0 up to and including 2π. Hence the custom node.

Superformula Loop Driver 2

This calculates the z-value and scale for an individual loop:

Superformula Loop Driver 2

So I wanted the pumpkin to be roughly spherical, which meant that I needed to generate a series of circularish/pumpkin-shaped loops positioned and scaled like lines of latitude on the earth. So  I’m using polar coordinates in a vertical plane to generate the z and scale values for Superformula Loop.

Why didn’t I just include this calculation inside Superformula Loop? Three reasons (similar to the reasons for helper nodes):

  1. Each node just does one thing: You can test and debug it in isolation
  2. Each node is simpler, and easier to understand
  3. I might want to re-use either the Loop node or the Driver node (tweaked) in other solutions.

Why is it called Superformula Loop Driver 2? Because Superformula Loop Driver 1 didn’t work.


This is the main layout:


The bottom part of the layout generates a sequence of angles (in the vertical plane) to position the loops vertically. Half a circle (180 degrees) is π radians, so I space the top and bottom loops 0.1 radians off vertical, and then divide the remaining vertical angle by the bottom-left Number input to generate the loops.

The top part of the layout has the parameter input nodes for the superformula (which is driven by the Map), and then over on the right-hand side, there is the Loft Form node, which actually creates the form. the two Watch nodes are just debugging aids, so I can see the list of loops in the top Watch, and the list of angles in the bottom one.

Whew! That’s all there is to it.

Just a couple of caveats: The code runs slowly. If you want to try it out, I’d start by putting a small number like 4 or 8 into the bottom-left number node in Superformula Loop because that will make it complete faster. I’d restart Dynamo if you want to change this number again, because it will probably break the loft if you change it on the fly. The code only runs with the debug switch on. As Zach found, it only runs in Revit, not in Vasari (not sure why not just yet). If you try it, thank you, and do let me know how you get on!

And here’s the source.

Sunday, November 4, 2012

Revitator’s Punkinator

A week ago today I was determinedly hacking away at Dynamo, intent on creating a pumpkin, any kind of pumpkin, for Zach Kron’s 4th Annual Parametric Pumpkin Carving. My first two attempts at pumpkin-carving had merely revealed my lack of skill with nested profiles and adaptive components, and time was running out.

So I fell back on an approach I’d used previously (in particular for the twisting tower I presented at Manchester Revit User Group (MRUG) back in September): Build a loft from a series of loops.

Now Dynamo, being Alpha code, can be a bit tricky, and I didn’t get the thing running at all until midnight. And then it ran glacially slow. But it did create pumpkins; or pumpkin-like things; or (depending on the parameters), totally un-pumpkin-like things. So I snapped a couple of screenshots, zipped the files up, wrote a quick explanation, and sent the whole lot off to Zach. And then went to bed thinking, ‘Well, at least I made something this year.’

And then, surprise, delight, my pumpkin won Mostest Parametric!

Just goes to show: Put the effort in and turn up to the event, you might just be lucky!