June 30, 2017

Dynamo: Rounding Up

I was looking to try to automate some life-safety-related tasks in Revit® today, specifically related to occupant load calculations, and set out to create a Dynamo graph. I wanted to be able to round up the Area parameter value derived from an Area object, so that a whole number would be used (matching the calculated value in a Schedule) and I also wanted to round up any "fraction of a person" that results from dividing the Area value by the area per occupant value (as specified in the governing building code). I did not see a "Round Up" node in the standard Dynamo nodes, just two different Round nodes, one to round to the nearest whole number and one where you can specify the number of decimal places in the rounded number. (I am currently using the 1.2 release - yes, I know I am behind.) So I set out to create my own Round Up node. NOTE: As my interest here is with positive numbers and rounding up to the next largest whole number for values that are not already a whole number, I did not worry about how negative numbers should be treated (should they round toward or away from zero?). If your application does involve negative numbers, you will need to determine which direction they should round, and adjust the node definition accordingly.

The image above shows the definition of the Round Up node that I created. (As always, you can select an image to see the full-size version.) The math behind it is fairly straightforward:
  • The Input node takes a number as input.
  • The Math.Floor node takes the input number and truncates any fractional part.
  • The x subtract y. node subtracts the result of the Math.Floor node from the original number, to determine the fractional value (if any).
  • The x less y? node compares that fractional value to zero, generating a value of true if it is greater than zero, or false if not.
  • The If node uses that true/false value as the test input, and passes along a value of 1 if the test value is true or 0 if the test value is false.
  • Finally, the Adds x to y. node adds the truncated result of the Math.Floor node to the value of the If node, and passes this along to the Output node as the result of this custom node.

So, if there is a fractional amount, one is added to the whole number portion of the input value; otherwise, zero is added to the whole number portion, which is "rounding up".

While testing this as part of my Dynamo graph, I noticed that one of the Area values, which was reporting as 100 square feet in Revit (after using the RoundUp function in Revit) was unexpectedly rounding up to 101. I took a look at the node values and discovered that an Area that was inside boundaries that formed a 10'-0" square was reporting an area of 100.000000000002 square feet inside Dynamo. While I always want to round any true fractional value up, I decided that it was unreasonable to assign two occupants to that 100 square foot Office (at 100 square feet per occupant) for a non-zero value in the twelfth decimal place. In my mind, that is a computational error. So I came up with another custom node, called Round Up with Floor (see image below).
This custom node definition has all of the same nodes as the Round Up node, except the Code Block that supplies the zero value to the x less y? node is replaced with a second Input node. That allows you to specify the value above which the rounding up will occur. I still need to do additional testing to determine at what value the RoundUp function in Revit will actually round up. For my first test of the Round Up with Floor node, I used a floor value of 0.000001 (one millionth of a square foot), and that eliminated the rounding up of the one area with the very small fractional amount.

No comments: