Wednesday, July 3, 2013

Moving to bimwood

Well, for one reason and another I haven’t been happy with the Revitator name for a while.

And now I’ve finally taken the plunge and set up a whole new blog over at:

http://bimwood.blogspot.co.uk/

There are a couple of posts there already, exploring the new Lacing functionality in Dynamo. I hope they’re useful to you.

Thank you for reading this Revitator blog so far, and I hope you’ll come and join in the fun at the new blog!

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:

GetCoordinatePlaneReferenceYZ

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:

Superformula

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.

Superformula

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:

Abs

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

x^y

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:

2pin

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.

Punkinator

This is the main layout:

Punkinator

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!

Tuesday, October 23, 2012

DesignScript - Points

Autodesk Labs have just released DesignScript as a Technology Preview, so I’ve been looking at porting some of Nathan Miller’s Proving Ground RevitPythonScript examples, just to see how DesignScript works. This first post summarises the Point Creation examples:

Single Point

This is the simplest example: Create a point at specified coordinates.

import("ProtoGeometry.dll");

// create a point with x, y, and z coordinates

x_pos = 10;

y_pos = 10;

z_pos = 0;

pCoord = Point.ByCoordinates(x_pos, y_pos, z_pos);


This was adapted from the example on page 17 of the DesignScript Language Manual, version 09. It is very simple: Import the ProtoGeometry dll, define the coordinates and call Point.ByCoordinates(x,y,z).


Point by Coordinates


Row of Points


Create a row of points at specified xy values:

import("ProtoGeometry.dll");
// create a row of points
x_pos = 0..100..10;
y_pos = 0..100..10;
z_pos = 0;
pCoord = Point.ByCoordinates(x_pos, y_pos, z_pos);


This example is hardly more complex. Just by defining the x and y coordinates as ranges rather than single values, Point.ByCoordinates generates a row of points.


Row of Points


Grid of Points


Create a grid of points:

import("ProtoGeometry.dll");
// create a grid of points
x_pos = 0..100..10;
y_pos = 0..100..10;
z_pos = 0;
pCoord = Point.ByCoordinates(x_pos<1>, y_pos<2>, z_pos);


And just by making a tiny change to the code, adding the Replication Guides <1> and <2> to the Point.ByCoordinates call, Point.ByCoordinates generates a grid of points.


Grid of Points


Sine Wave Points


Create a grid of points, where the z-value of each point is a function of the x and y coordinates.

import("ProtoGeometry.dll");
import("Math.dll");


def RadiansToDegrees(n)
{
    return = n * 360/(2 * 3.142);
}


def CosXPlusSinY(x, y)
{
    return = Math.Cos(RadiansToDegrees(x)) + Math.Sin(RadiansToDegrees(y));
}


def PointZ(x, y)
{
    z = CosXPlusSinY(x, y);
    s = Print(z);
    return = Point.ByCoordinates(10 * x, 10 * y, 10 * z);
}


// create a grid of points where z = f(xy)
x_pos = 0..30;
y_pos = 0..30;


pCoord = PointZ(x_pos<1>, y_pos<2>);


Now this is suddenly much more complex. The simple range and replication guide tricks work for simple cases, but are harder to apply in more real-world examples.


I wanted to use the replication guides to generate the grid (I could have fallen back on nested loops, of course, but that would be a shame). There doesn’t seem to be a way to include the z function inline, like this:


pcoord = Point.ByCoordinate(x_pos<1>, y_pos<2>,CosXPlusSinY(x_pos,y_pos))   //fail


So I wrapped the z-calculation and the Point.ByCoordinates call in a custom function, PointZ(x,y). In this way, I could use the replication guides in the call to PointZ, and


The other slight complexity is that both Python and Dynamo use radian values for their trig functions, DesignScript expects degrees. Hence the RadiansToDegrees function (with a dodgy value for pi because, well, I haven’t been able to find the correct syntax for DesignScript’s PI() function).


Sine Wave Points


And here’s the source: DesignScript Points examples.

Friday, October 19, 2012

Dynamo - Indexed Family Instances

Once classic way to create forms in Revit is to place multiple family instances that are driven by an indexed instance parameter. Zach Kron gives a good explanation in his post Parametric Patterns VI: Increment. The only tedium is in placing and indexing all the instances.

I wondered how hard it would be to place and index the instances using Dynamo, and this is the result:

Indexed Family Instances

The Family Type Selector and the Instance Parameter Selector allow you to choose the family type to place and the driving parameter. The Build Sequence node and its inputs generate the sequence of values for the driving parameter.

The Map node calls my user node ‘Family Instance Creator – Indexed’ once for each number in the sequence, and each time, the node creates a family instance and sets the driving parameter:

Family Instance Creator - Indexed

This is fairly straightforward. All the instances are placed at 0,0,0. The Family Instance Creator node creates the instance, and the Set Instance Parameter node sets the driving parameter.

And here is the result, using a simple twisting box family:

Twisting Tower

Finally, here is the source: Indexed Family Instances.